Amazon Location Service 位置情報基盤 本番運用 Vol1 — 地図/Routes/ジオフェンス

目次

1. 位置情報の本番課題とAmazon Location Service全体像

fig01: Amazon Location Service全体像アーキテクチャ
fig01: Amazon Location Service全体像アーキテクチャ
この記事で得られること

  • 2024年秋に刷新されたスタンドアロン型 Maps / Places / Routes API の設計思想と旧リソースベース方式との違い
  • 地図表示・ジオコーディング・ルート最適化・ジオフェンスを組み合わせた本番アーキテクチャの設計パターン
  • APIキー / Cognito Identity Pools / IAM の3認証方式を要件から選定する判断基準
  • リクエスト課金の料金構造を理解し、無料枠とキャッシュを活用してコストを最適化する方法
  • Google Maps Platform からの段階的移行を支える Migration SDK の活用戦略

1-1. 本記事のゴール

配送追跡アプリに地図を組み込もうとすると、すぐに複数の壁にぶつかります。Google Maps Platform の月次請求が予想以上に膨らんだ、位置データをクラウド外に送信することへの社内セキュリティ審査が通らない、DynamoDB や EventBridge との連携を自前で実装しなければならない——こうした課題は、AWS 上でシステムを構築しているチームが共通して直面する問題です。

Amazon Location Service はこれらの課題に正面から応えるマネージドサービスです。地図タイル配信・住所検索・ルート計算・ジオフェンス・デバイス追跡の5機能をひとつのサービスに統合し、AWS IAM / Cognito と組み合わせたセキュアな認証、EventBridge や Lambda との直接連携、そしてリクエスト単位の従量課金を提供します。

本記事では、2024年秋に刷新されたスタンドアロン型 API を前提に、Maps / Places / Routes / Geofences / Trackers の5機能を横断した本番構築の実践知識を体系的に解説します。Google Maps Platform からの移行を検討しているチーム、位置情報基盤を新規設計するチームの両方を対象としています。

1-2. 読者像

本記事が想定する読者は、AWS 上でアプリケーションを開発・運用している中級以上のエンジニアです。IAM ポリシーの基本的な読み書き、Lambda や EventBridge の概念的な理解があれば、本文を通読できます。

位置情報 API の利用経験がなくても理解できるよう、API 設計の考え方から解説しています。一方、Google Maps JavaScript API や Places API の経験者向けに、対応する Amazon Location Service API と移行時の注意点も随所で補足しています。

1-3. 新旧 API 構成の違いと2024年刷新の全体像

Amazon Location Service は2024年秋に API 設計を大幅に刷新しました。この刷新は「旧リソースベース方式」から「新スタンドアロン方式」への移行であり、本記事ではこの新スタンドアロン方式を前提として解説します。

旧リソースベース方式(参考)

旧来の API では、地図を使う前に Map リソース、住所検索を使う前に PlaceIndex リソース、ルート計算を使う前に RouteCalculator リソースを事前作成する必要がありました。リソースごとにデータプロバイダー(Esri / HERE など)を固定で選択し、ARN を API コールに含めるという設計です。この方式は現在も利用可能ですが、新規開発では推奨されません。

新スタンドアロン方式(本記事の前提)

2024年秋に発表された Enhanced Maps / Places / Routes API は、事前リソース作成が不要なスタンドアロン型です。API を直接呼び出すだけで地図タイルや検索結果・ルートを取得できます。データプロバイダーはリクエストごとにパラメータで選択でき、Esri / HERE / GrabMaps / Open Data(OpenStreetMap ベース)から用途に応じて使い分けられます。

新旧の主な違いを整理します。

項目旧リソースベース方式新スタンドアロン方式
事前リソース作成必須(Map / PlaceIndex / RouteCalculator)不要
データプロバイダー選択リソース作成時に固定リクエストごとに選択可能
API キー対応対応(2023年7月より)対応(推奨)
Enhanced Places 機能非対応営業時間・電話番号等のリッチ詳細・Autocomplete
ルート最適化(多拠点)非対応OptimizeWaypoints 対応
到達圏計算(Isoline)非対応CalculateIsolines 対応

5機能の役割と全体像

Amazon Location Service は以下の5機能で構成されます。

  • Maps: 地図タイル配信と静的地図画像生成。MapLibre GL JS など標準ライブラリとの統合が容易です。
  • Places: ジオコーディング(住所→緯度経度)・逆ジオコーディング・テキスト検索・オートコンプリート・周辺検索・住所検証を提供します。
  • Routes: 車・トラック・徒歩・スクーター・交通機関の各移動手段に対応したルート計算。多拠点配送の Waypoint 最適化、到達圏(Isoline)計算、通行料金計算をサポートします。
  • Geofences: 地理的境界(ポリゴン)を定義し、デバイスの ENTER / EXIT イベントを EventBridge に連携します。
  • Trackers: モバイルデバイスや IoT デバイスの位置を収集・追跡し、ジオフェンスと連動して位置イベントを生成します。

図01 は5機能の関係と、EventBridge / Lambda / DynamoDB との連携フローを示しています。

データプロバイダーの選択指針

Amazon Location Service は複数のデータプロバイダーからデータを取得します。

  • Esri: 詳細な地図データと企業向けサポート。日本語住所の精度が高く、国内商用利用に適しています。
  • HERE: 物流・車両追跡に強みを持つプロバイダー。トラックルーティングや交通情報の精度が高いです。
  • GrabMaps: 東南アジア(シンガポール・インドネシア等)向けに最適化されています。
  • Open Data: OpenStreetMap ベースの無償データ。コスト最小化が優先で精度要件が緩い用途に向きます。

プロバイダーの利用可否はリージョンと API によって異なります。本番環境では、事前に対象リージョンでの利用可否と利用規約(特に結果のキャッシュ・保存ポリシー)を確認してください。

1-4. 位置情報の本番課題と Location Service が解決するもの

位置情報機能を本番環境に投入すると、開発段階では想定しなかった問題が顕在化します。主な課題を4軸で整理します。

課題1: コスト爆発

Google Maps Platform は無償枠(月 200 ドル相当)を超えると従量課金が急増します。地図タイルのリクエスト数は予想より桁違いに多くなることが多く、スクロールや拡大縮小ごとに複数タイルが発生するためです。Amazon Location Service は同等機能でより低単価のリクエスト課金を提供しており、AWS の既存クレジットや無料枠との組み合わせでコストを抑えられます。

課題2: データプライバシーと規制

医療・金融・公共系システムでは、位置データをサードパーティへ送信することへの法的・契約的制約があります。Amazon Location Service は AWS リージョン内でデータを処理し、ユーザーの位置情報が Amazon の基盤サービス改善に使用されません(Terms of Service 記載)。データレジデンシー要件を満たした上で位置情報機能を実装できます。

課題3: AWS サービスとの統合コスト

外部の地図 API を AWS システムに統合するには、API キーの Secrets Manager 管理、Lambda からの HTTP 呼び出し、EventBridge との手動連携など、多くのグルーコードが必要です。Amazon Location Service は IAM ポリシーでアクセス制御でき、Tracker からのジオフェンスイベントが EventBridge に直接連携されます。

課題4: スケーラビリティと可用性

自前の地図タイルサーバーやルーティングエンジンを運用する場合、ピーク時のスケールアウトや可用性確保が運用負荷になります。Amazon Location Service はマネージドサービスとして自動スケールし、AWS の SLA に準拠した可用性を提供します。

1-5. Google Maps Platform との比較・移行ナビ

Amazon Location Service を Google Maps Platform と比較した場合の主な差異を整理します。

項目Google Maps PlatformAmazon Location Service
認証API キーのみAPIキー / Cognito / IAM
データ主権Google クラウドAWS リージョン内処理
AWS 統合手動グルーコード必要IAM / EventBridge / Lambda とネイティブ連携
地図ライブラリGoogle Maps JS API 専用MapLibre GL JS(OSS)で標準化
ルート最適化対応(Direction API)OptimizeWaypoints(新API)で対応
ジオフェンス非対応(自前実装)マネージド(EventBridge 連携)
デバイス追跡非対応(自前実装)マネージド Tracker
無料枠月 200 ドルクレジット初3ヶ月の月次リクエスト枠
料金モデルリクエスト従量(高単価)リクエスト従量(比較的低単価)

Google Maps Platform から移行する場合、Amazon が提供する Maps SDK for iOS/Android(Migration SDK) が利用できます。この SDK は Google Maps SDK の主要 API を互換レイヤーで提供し、ネイティブアプリのコード変更量を最小化します。2025年に対応 API 範囲がさらに拡張されており、段階的な移行戦略と組み合わせると効果的です。移行設計の詳細は§7で解説します。

ウェブアプリケーションでは Google Maps JavaScript API から MapLibre GL JS ベースの Amazon Location Service へ切り替えることになります。MapLibre はオープンソースであり、地図スタイルのカスタマイズ自由度が高く、ベンダーロックインを回避できる点も移行理由のひとつです。

本記事の構成と読み方

  • §2: Maps API — 地図タイル配信と MapLibre GL JS 統合
  • §3: Places API — ジオコーディング・検索・住所検証
  • §4: Routes API — ルート計算・Waypoint 最適化・Isoline
  • §5: Geofences & Trackers — 位置イベント駆動設計
  • §6: 認証・運用・コスト — APIキー・Cognito・料金最適化
  • §7: 実戦統合パターン — Google Maps 移行・物流・店舗 E2E
  • §8: 詰まりポイントとアンチパターン

認証・料金だけを先に確認したい場合は§6へ、移行設計を優先する場合は§7へ直接進んでください。


2. Maps — 地図タイルとスタンドアロンMaps API

fig02: Maps APIの地図タイル配信とMapLibre統合構成
fig02: Maps APIの地図タイル配信とMapLibre統合構成

2-1. 2024年刷新スタンドアロンMaps APIの構成

§1で概観したように、Amazon Location ServiceのMaps機能は2024年10月に「リソースベースAPI」から「スタンドアロンMaps API」へ刷新されました。Maps固有の構成変更を本節で整理します。

旧リソースベースMapリソースとの構成差

旧方式では、地図を表示する前に以下の手順でMapリソースを事前作成する必要がありました。

  1. コンソールまたは CreateMap API でMapリソースを作成する
  2. 作成時にデータプロバイダー(Esri/HERE等)とスタイル(Streets/Navigation等)を固定で選択する
  3. CloudFormation/CDKでのリソース定義が必要で、デプロイパイプラインの管理が複雑になる
  4. APIコールに作成済みリソースの名前(MapName)を含める

旧APIでのタイル取得(参考):

# 旧リソースベースAPI: MapName が必要
import boto3
client = boto3.client('location', region_name='ap-northeast-1')
response = client.get_map_tile(
 MapName='my-esri-streets-map',# 事前作成した Map リソース名
 Z='12', X='3632', Y='1614'
)

新スタンドアロンMaps APIではこれらの事前作業が不要になりました。

新スタンドアロンMaps APIの設計

新APIは geo-maps サービスとして提供されます(boto3のサービス名が location から変更)。

# 新スタンドアロンAPI: リソース作成不要
import boto3
client = boto3.client('geo-maps', region_name='ap-northeast-1')
response = client.get_tile(
 Tileset='VectorEsriStreets',# スタイルをパラメーターで都度指定
 Z='12', X='3632', Y='1614',
 Key='v1.public.xxxxx...'  # APIキー認証(読み取り系)
)

2024年10月の刷新では17のMaps APIが更新・追加されました(新規7本+更新10本)。主な新エンドポイントは以下の通りです。

エンドポイント(新API)説明
GetTileベクター/ラスタータイルの取得
GetStyleDescriptorスタイルJSON定義の取得(MapLibre用)
GetGlyphsフォントグリフの取得(テキストラベル描画用)
GetSpritesスプライト画像の取得(アイコン類)
GetStaticMap静的地図画像(PNG)の生成

GetGlyphsGetSprites はMapLibreが内部で自動的に発行するリクエストです。リクエスト数の見積もりに含め忘れると料金見積もりが実態と乖離するため注意が必要です。

新旧APIの最終確認チェックリスト

移行・新規実装の前に以下を確認してください。

  • boto3の client() サービス名は geo-maps(旧APIは location
  • MapLibre GL JSのスタイルURLは https://maps.geo.{region}.amazonaws.com/maps/v0/style/{style} 形式
  • /maps/v0/maps/{MapName}/ 形式のURLは使用しない
  • APIキーのスコープに geo:GetTilegeo:GetStyleDescriptorgeo:GetGlyphsgeo:GetSprites を含める

2-2. 地図タイル・スタイル・Static Maps

スタンドアロンMaps APIはベクタータイル、ラスタータイル、静的地図画像(Static Maps)の3形式を提供します。

ベクタータイル

ベクタータイルは地図の形状データ(座標・属性)を数値形式で配信し、クライアント側のMapLibre GL JSがWebGLでレンダリングします。

主な特徴:
任意ズームで鮮明: 数値ベースのため拡大縮小しても輪郭がぼけない
スタイルの動的切り替え: ライト/ダーク等のテーマ変更をクライアント側で完結できる
軽量転送: 同一エリアのラスタータイルよりデータサイズは小さい傾向がある
要件: WebGL対応ブラウザとMapLibre GL JSが必要

ラスタータイル

ラスタータイルはPNG画像として配信されます。

主な特徴:
広い互換性: WebGLが不要のため旧ブラウザや組み込み環境でも表示可能
実装がシンプル: Leafletなどの標準的な地図ライブラリで対応できる
スタイル動的変更は不可: テーマ変更には別スタイルを再取得する必要がある

本番環境では、インタラクティブなWebアプリにはベクタータイル、レガシーシステムや帯域が限られた環境にはラスタータイルを選択します。

スタイル一覧

スタンドアロンMaps APIで使用可能なプリセットスタイルを以下に示します。

Esriスタイル:

スタイル名特徴推奨用途
VectorEsriStreets汎用の都市地図・日本語住所の精度が高い一般的なWebアプリ・GIS
VectorEsriNavigationナビゲーション向け・道路情報重視配送・ドライバー向けUI
VectorEsriDarkGrayCanvasダークテーマ・UI背景との一体感ダッシュボード・管理画面
VectorEsriLightGrayCanvasライトテーマ・シンプルなデザイン業務アプリ・管理画面
VectorEsriTopographic地形・等高線を表示ハイキング・アウトドア系

HEREスタイル:

スタイル名特徴推奨用途
VectorHereExploreHEREの標準地図・交通情報充実一般的なWebアプリ
VectorHereExploreTruck高さ・重量制限を地図上に表示物流・大型車両管理
VectorHereContrastコントラスト強調・視認性重視アクセシビリティ対応
RasterHereExploreSatellite航空写真(ラスター形式)土地確認・農業・建設

Open Dataスタイル(追加コストなし):

スタイル名特徴
VectorOpenDataStandardLightOpenStreetMapベース・ライトテーマ
VectorOpenDataStandardDarkOpenStreetMapベース・ダークテーマ
VectorOpenDataVisualizationLightデータ可視化向けの薄いスタイル

Open Dataスタイルはリクエスト無料で利用できますが、詳細な商業施設情報や交通データはEsri/HEREに比べて限定的です。本番商用アプリにはEsriまたはHEREを推奨します。

データプロバイダー別の特徴

プロバイダー強み主な用途
Esri詳細な都市・地形情報・POI充実一般地図表示・GISアプリ
HEREリアルタイム交通・ルート情報が強い配送・ナビゲーション
GrabMaps東南アジアの詳細地図東南アジア向けサービス
Open Data無料・オープンソースベース開発・プロトタイプ

同一アプリ内でも機能ごとに異なるプロバイダーを組み合わせることが可能です。例えば地図表示にEsri、ルート計算にHEREを使うといった構成が選択できます。

Static Maps API

指定した座標・ズームレベル・サイズで静的地図画像(PNG)を生成します。

主な用途:
– OGP/SNSシェア画像への地図埋め込み
– メール・PDF・帳票への地図表示
– サムネイル・プレビュー生成

import boto3

client = boto3.client('geo-maps', region_name='ap-northeast-1')

response = client.get_static_map(
 Width=800,
 Height=600,
 Center='-122.3321,37.5630',# 経度,緯度
 Zoom=12,
 ScaleBarUnit='Kilometers',
 Key='v1.public.xxxxx...'
)

from pathlib import Path
Path('map_preview.png').write_bytes(response['Blob'].read())

ポイント: サービス名は geo-maps を使用します。旧APIの location サービスの GetStaticMap とはエンドポイントが異なります。ピン・ポリゴン・ラインのオーバーレイも GeoJSON パラメーターで指定できます。

2-3. MapLibre GL JS統合とフロントエンド実装

MapLibre GL JSはオープンソース(MIT License)のWebGLベース地図レンダリングライブラリです。Amazon Location Serviceの公式ドキュメントもMapLibre統合を標準ガイドとして採用しており、Amplify Geoでも内部実装として使用されています。

必要なパッケージ

{
  "dependencies": {
 "maplibre-gl": "^3.6.0",
 "@aws/amazon-location-utilities-auth-helper": "^1.1.0"
  }
}

maplibre-gl のバージョンは必ず固定することを強く推奨します。v4系でAPIの一部が変更されており、認証ヘルパーとの互換性問題を引き起こすことがあります。

実装手順(Vanilla JS)

Step 1: HTMLのセットアップ

<!DOCTYPE html>
<html>
<head>
  <link href="https://unpkg.com/maplibre-gl@3.6.0/dist/maplibre-gl.css"
  rel="stylesheet" />
  <script src="https://unpkg.com/maplibre-gl@3.6.0/dist/maplibre-gl.js"></script>
</head>
<body>
  <div id="map" style="width: 100%; height: 500px;"></div>
  <script type="module" src="./app.js"></script>
</body>
</html>

Step 2: APIキー認証で地図を表示する

地図表示・タイル取得などの読み取り操作にAPIキー認証を使用します。ジオフェンス追加等のリソース操作にはAPIキーを使用できません。

import { withAPIKey } from "@aws/amazon-location-utilities-auth-helper";

const region = "ap-northeast-1";
const apiKey = "v1.public.xxxxxx...";
const style = "VectorEsriStreets";

const authHelper = await withAPIKey(apiKey);

const map = new maplibregl.Map({
  container: "map",
  style: `https://maps.geo.${region}.amazonaws.com/maps/v0/style/${style}`,
  center: [139.7671, 35.6812],// [経度, 緯度] ※順序に注意
  zoom: 12,
  ...authHelper.getMapAuthenticationOptions()
});

center には [経度, 緯度] の順序で指定します。Google Maps APIの {lat, lng} 形式と逆順のため、移行時の混同に注意してください。

Step 3: Cognito認証(書き込み操作が必要な場合)

ジオフェンス追加・デバイス位置書き込み等のリソース操作が必要な場合はCognito Identity Poolsを使用します。

import { withIdentityPoolId } from "@aws/amazon-location-utilities-auth-helper";

const authHelper = await withIdentityPoolId(
  "ap-northeast-1:xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
);

const map = new maplibregl.Map({
  container: "map",
  style: "https://maps.geo.ap-northeast-1.amazonaws.com/maps/v0/style/VectorEsriStreets",
  center: [139.7671, 35.6812],
  zoom: 12,
  ...authHelper.getMapAuthenticationOptions()
});

Step 4: マーカーとポップアップ

map.on('load', () => {
  // カスタムカラーマーカーの追加
  const marker = new maplibregl.Marker({ color: "#FF5733" })
 .setLngLat([139.7671, 35.6812])
 .addTo(map);

  // ポップアップ付きマーカー
  const popup = new maplibregl.Popup({ offset: 25 })
 .setHTML("<strong>配送先</strong><p>東京都千代田区</p>");

  new maplibregl.Marker({ color: "#3380FF" })
 .setLngLat([139.7671, 35.6812])
 .setPopup(popup)
 .addTo(map);
});

Amplify Geo統合(React環境)

AWS Amplifyを使用するReactアプリでは @aws-amplify/ui-react-geo パッケージがLocation Serviceを抽象化し、少ないコードで地図コンポーネントを実装できます。

npm install @aws-amplify/ui-react-geo @aws-amplify/geo aws-amplify
import { Amplify } from 'aws-amplify';
import { MapView } from '@aws-amplify/ui-react-geo';
import '@aws-amplify/ui-react-geo/styles.css';

Amplify.configure({
  geo: {
 AmazonLocationService: {
maps: {
  items: {
 'aws-location-map': { style: 'VectorEsriStreets' }
  },
  default: 'aws-location-map',
},
region: 'ap-northeast-1',
 }
  }
});

function LocationMap() {
  return (
 <MapView
initialViewState={{
  longitude: 139.7671,
  latitude: 35.6812,
  zoom: 12
}}
 />
  );
}

Amplify Geoを使う場合、Amplify CLIの amplify add geo コマンドでIAMポリシー・Cognito Identity Poolの設定を自動生成できます。手動設定より確実で、本番環境への展開工数を削減できます。

バージョン管理の注意点

認証ヘルパー(@aws/amazon-location-utilities-auth-helper)のメジャーバージョンはMapLibreのメジャーバージョンと密結合しています。package.jsonでのバージョン固定を推奨し、バージョンアップ時は必ず動作確認を行ってください。依存関係の固定には package-lock.json または yarn.lock をGitにコミットし、npm ci でビルドすることも有効です。


3. Places — ジオコーディングと検索

fig03: Places APIのジオコーディング・検索フロー
fig03: Places APIのジオコーディング・検索フロー

Amazon Location ServiceのPlaces機能は、2024年10月の刷新により完全スタンドアロンAPI体系へと移行しました。旧来のリソースベースAPI(PlaceIndexリソースの作成が前提)は廃止対象となり、GeocodeReverseGeocodeSearchTextSearchNearbyAutocompleteSuggestGetPlace の7エンドポイントが独立して提供されています。

データプロバイダーはEsri・HERE・GrabMaps・Open Dataから用途に応じて選択できます。日本国内での住所検索精度にはHEREまたはEsriが推奨されます。

3-1. Geocode / ReverseGeocode

Geocode — 住所→座標変換:

Geocode APIは住所テキストから地理座標(緯度・経度)へ変換するジオコーディングを担います。旧APIのSearchPlaceIndexForTextからの移行では、PlaceIndexリソースの作成が不要になり、Boto3クライアント名もlocationからgeo-placesへと変わります。

import boto3

client = boto3.client("geo-places", region_name="ap-northeast-1")

response = client.geocode(
 QueryText="東京都千代田区千代田1番地",
 Language="ja",
 MaxResults=5,
 AdditionalFeatures=["TimeZone", "Access", "Contacts"]
)

for result in response["ResultItems"]:
 pos = result["Position"]  # [経度, 緯度] の順
 label = result["Address"]["Label"]
 score = result.get("Score", 0)
 print(f"{label}: 緯度={pos[1]:.6f}, 経度={pos[0]:.6f} (スコア={score:.2f})")

AdditionalFeatures に指定できる主なオプションは以下のとおりです。デフォルトでは住所情報と座標のみ返却されます。

オプション返却内容
Core基本住所コンポーネント(デフォルト)
TimeZoneタイムゾーン名(例:Asia/Tokyo)・UTCオフセット
Access入口アクセスポイント座標(AccessPoints 配列)
Contacts電話番号・ウェブサイトURL・メールアドレス

住所コンポーネント構造:

レスポンスのAddressオブジェクトは住所を構造化フィールドで返します。

フィールド内容
Address.Label完全住所文字列東京都千代田区千代田1番地
Address.Street番地・町名千代田1番地
Address.Locality市区町村千代田区
Address.Region都道府県東京都
Address.PostalCode郵便番号100-0001
Address.Country.Code3国コード(ISO 3166-1 alpha-3)JPN
Position[経度, 緯度] 配列[139.7671, 35.6812]
Scoreマッチ信頼度(0〜1)0.98

ReverseGeocode — 座標→住所変換:

ReverseGeocode APIは緯度・経度から最寄りの住所・施設情報を取得します。旧SearchPlaceIndexForPositionに相当します。タクシーアプリの乗降地表示・配達先の住所確認・地図クリックによる住所特定に活用されます。

response = client.reverse_geocode(
 QueryPosition=[139.7671, 35.6812],# [経度, 緯度] の順
 Language="ja",
 MaxResults=3,
 AdditionalFeatures=["TimeZone"]
)

for result in response["ResultItems"]:
 label = result["Address"]["Label"]
 postal = result["Address"].get("PostalCode", "")
 region = result["Address"].get("Region", "")
 print(f"{label} ({postal} {region})")

旧APIからの移行時の注意点:

旧PlaceIndex APIと新スタンドアロンAPIではPlaceIdの形式が互換性を持ちません。旧PlaceIdGetPlaceに渡しても正しく動作しないため、移行時にはデータベースに保存済みのPlaceIdを全件再取得する必要があります。段階移行では旧APIと新APIを並行稼働させ、両方のPlaceIdをマッピングして対応することを推奨します。

3-2. SearchText / SearchNearby / Autocomplete / Suggest

SearchText — フリーワード全文検索:

SearchText APIは施設名・カテゴリ・住所等のフリーワードから場所を検索します。地図上の検索ボックス実装や、バックエンドでの住所候補取得に最適です。

response = client.search_text(
 QueryText="ラーメン 新宿",
 FilterCircle={
  "Center": [139.7003, 35.6938],
  "Radius": 2000  # メートル
 },
 Language="ja",
 MaxResults=20,
 AdditionalFeatures=["Details", "TimeZone", "Contacts"]
)

for result in response["ResultItems"]:
 title = result["Title"]
 pos = result["Position"]
 categories = [c["Name"] for c in result.get("Categories", [])]
 phones = result.get("Contacts", {}).get("Phones", [])
 print(f"{title}: {pos}, 電話={phones[:1]}")

AdditionalFeaturesDetails を含めると、営業時間・電話番号・ウェブサイト・料理ジャンル(FoodTypes)等のリッチ詳細が一括取得できます。旧PlaceIndexではGetPlaceを別途呼び出す必要がありましたが、2024年刷新により1回のAPIコールで完結するため、レイテンシとAPIコール数を削減できます。

SearchNearby — 近傍POI検索:

SearchNearby APIは指定座標周辺のPOIを距離順で返します。カテゴリフィルタと組み合わせることで「現在地から1km以内のコンビニ」などの絞り込みが可能です。

response = client.search_nearby(
 QueryPosition=[139.7003, 35.6938],
 QueryRadius=1000,
 Filter={
  "IncludeCategories": ["Retail.Convenience"],
  "IncludeCountries": ["JPN"]
 },
 Language="ja",
 MaxResults=20,
 AdditionalFeatures=["Details"]
)

for result in response["ResultItems"]:
 title = result["Title"]
 dist = result.get("Distance", 0)
 addr = result["Address"]["Label"]
 print(f"{title}: {addr} ({dist:.0f}m離)")

Distance フィールドに中心座標からの距離(メートル)が含まれるため、「○m以内」表示に直接利用できます。Filter.IncludeCategories はHEREカテゴリ体系に準拠し、EatAndDrinkRetailTransport.PublicTransitHealthcare.Hospitalなど多数のカテゴリコードが利用できます。

Autocomplete — 入力補完:

Autocomplete APIはユーザーのタイプ中テキストから補完候補を提案します。レスポンスが高速(通常数十ms)で、検索ボックスのリアルタイム補完UIに適しています。

response = client.autocomplete(
 QueryText="東京タワ",
 BiasPosition=[139.7671, 35.6812],
 Language="ja",
 MaxResults=5,
 AdditionalFeatures=["Core"]
)

for result in response["ResultItems"]:
 text = result["Title"]["Text"]
 highlights = result["Title"].get("Highlights", [])
 place_id = result.get("PlaceId")
 print(f"{text} (PlaceId: {place_id})")

Title.Highlights には入力テキストとのマッチ位置(StartIndexEndIndex)が含まれます。フロントエンドでユーザー入力部分を太字・色付き表示するUIに活用できます。補完候補確定後はPlaceIdを用いてGetPlaceで詳細情報を取得するフローが一般的です。

Suggest — クエリ候補提案:

Suggest APIはAutocompleteを拡張し、場所の候補(Place型)に加えてクエリレベルの提案(Query型)も返します。「新宿 カフェ」と入力した際に、個別の店舗名だけでなく「新宿カフェ特集」のようなクエリ候補も混在して提案されます。

response = client.suggest(
 QueryText="新宿 カフェ",
 BiasPosition=[139.7003, 35.6938],
 Language="ja",
 MaxResults=10
)

for result in response["ResultItems"]:
 item_type = result["SuggestResultItemType"]  # "Place" or "Query"
 if item_type == "Place":
  title = result["Place"]["PlaceWithDistance"]["Title"]
  print(f"[場所] {title}")
 elif item_type == "Query":
  query_text = result["Query"]["QueryText"]
  print(f"[クエリ] {query_text}")

リッチ詳細フィールド一覧(AdditionalFeatures=”Details”):

フィールド内容対応API
OpeningHours曜日別営業時間・祝日対応SearchText・SearchNearby・GetPlace
Contacts.Phones電話番号リスト同上
Contacts.WebsitesウェブサイトURLリスト同上
Contacts.Emailsメールアドレスリスト同上
Categoriesカテゴリコードと名称全Places API
FoodTypes料理ジャンルSearchText・SearchNearby
AccessPoints入口・アクセスポイント座標Geocode・GetPlace

3-3. 住所検証 (Address Validation) と保存ポリシー

Address Validation Core / Advanced:

住所検証はGeocodeとは独立したVerifyAddressエンドポイントで提供されます。入力住所の正規化・マッチスコア算出・郵便番号補完を担います。

  • Core(基本検証): 全データプロバイダーで利用可能です。入力住所を正規化し、各コンポーネントのマッチスコアを返します。住所フォームのバリデーションや一括住所クレンジングに適しています。
  • Advanced(高度検証): HEREデータプロバイダー選択時のみ利用可能です。宅配到達可能性の判定・建物レベルの住所品質グレード(ExcellentUndeliverable)・区画情報の付与が得られ、EC物流や郵便・配送業務の住所品質管理に有効です。
response = client.verify_address(
 QueryAddress={
  "AddressNumber": "1",
  "Street": "千代田",
  "Locality": "千代田区",
  "Region": "東京都",
  "Country": "JPN",
  "PostalCode": "100-0001"
 },
 IntendedUse="SingleUse"
)

result = response["ResultItem"]
overall_score = result["Match"]["Overall"]
normalized = result["Address"]["Label"]
grade = result.get("DeliveryRating", {}).get("Grade", "N/A")
print(f"正規化住所: {normalized}")
print(f"マッチスコア: {overall_score:.2f} | 配送品質グレード: {grade}")

保存ポリシー(IntendedUse)の選択:

Places APIのレスポンスデータは用途をIntendedUseパラメータで明示することが必須です。

意味用途例
SingleUse一時利用(永続保存不可)リアルタイム検索結果の表示・一時的な座標変換
Storage保存利用(DB永続化許可)DynamoDB・S3への住所データ保存・バッチ一括処理

Storage指定時はDynamoDB・S3等への永続化が許可されますが、データプロバイダーによっては追加料金や利用規約上の制約が生じます。本番実装前に必ずデータプロバイダーのサービス規約を確認してください。

料金と無料枠:

Places APIの料金はリクエスト単価制で、リージョンや時期によって変動します。初回利用開始から3ヶ月間は無料枠が適用され、Places系APIでは月2万リクエストまで無償で試用できます。AutocompleteSuggestSearchTextGeocodeより安価な単価が設定されています。本番導入前に必ず公式料金ページ(aws.amazon.com/location/pricing/)の当日値で見積もりを確認してください。


4. Routes — ルート計算と最適化

fig04: Routes計算/最適化フロー
fig04: Routes計算/最適化フロー

2024年11月にGAとなった Enhanced Routes API(サービス名前空間: geo-routes)は、旧 location 名前空間の Routes 機能を全面刷新したものです。旧 API では CreateRouteCalculator でリソースを事前作成する必要がありましたが、Enhanced Routes API はリソース不要のスタンドアロン設計となり、通行料金計算・Waypoint最適化・Isoline(到達圏)計算など、旧 API では提供されていなかった機能が追加されています。

4-1. CalculateRoutes (交通考慮・走行制限)

旧 API との構成差

旧 API は「リソース作成 → API 呼び出し」の2段階が必要でした。Enhanced Routes API ではリソース不要で、エンドポイントに直接リクエストを送信します。

比較項目旧 API(レガシー)Enhanced Routes API
リソースCreateRouteCalculator が必要不要(スタンドアロン)
API 名CalculateRoute(単数形)CalculateRoutes(複数形)
サービス名前空間locationgeo-routes
エンドポイントroutes.{region}.amazonaws.comroutes.geo.{region}.amazonaws.com
CLIaws location calculate-routeaws geo-routes calculate-routes
TravelModeCar / Truck / Walking の3種Car / Truck / Pedestrian / Scooter / Transit / Intermodal の6種
通行料金計算非対応Premiumティアで対応
代替ルート非対応最大5本

Python SDK の変更例は次のとおりです。

# 旧 API(非推奨)
client = boto3.client('location')
client.create_route_calculator(
 CalculatorName='my-calculator',
 DataSource='Esri'
)
client.calculate_route(CalculatorName='my-calculator', ...)

# Enhanced Routes API(2024 以降)
client = boto3.client('geo-routes')
client.calculate_routes(
 Origin=[139.6917, 35.6895],
 Destination=[135.5022, 34.6937]
)

CLI も同様に名前空間が変わっています。

# Enhanced Routes API
aws geo-routes calculate-routes \
  --origin '{"Position": [139.6917, 35.6895]}' \
  --destination '{"Position": [135.5022, 34.6937]}'

TravelMode の拡張

TravelMode説明ティア
Car自家用車・タクシー(デフォルト)Core
Truck大型トラック・商用車Core
Pedestrian徒歩Core
Scooterバイク・スクーターAdvanced
Transit公共交通機関Core
Intermodal複合交通手段(鉄道+バス等)Premium

交通情報の考慮 (Traffic)

DepartureTime(ISO-8601 形式)または DepartNow: true を指定すると、過去の交通パターンを参照して実態に近い所要時間を算出します。未指定の場合は交通情報なしの理論値が返されます。

{
  "Origin": {"Position": [139.6917, 35.6895]},
  "Destination": {"Position": [135.5022, 34.6937]},
  "DepartureTime": "2024-12-23T09:00:00Z",
  "OptimizeRoutingFor": "FastestRoute",
  "Traffic": {
 "Usage": "UseTrafficData"
  }
}

OptimizeRoutingFor には FastestRoute(時間優先)と ShortestRoute(距離優先)を指定できます。交通情報を無視したい場合は Usage: "IgnoreTrafficData" を指定します。

回避オプション (Avoid)

Avoid パラメータで有料道路・フェリー・ダート道・カスタムエリアなどを柔軟に回避できます。

"Avoid": {
  "TollRoads": true,
  "Ferries": true,
  "DirtRoads": true,
  "Tunnels": false,
  "ControlledAccessHighways": false,
  "UTurns": false,
  "Areas": [
 {
"Geometry": {
  "BoundingBox": [139.60, 35.60, 139.80, 35.80]
}
 }
  ]
}

カスタム回避エリアには BoundingBox のほか、Corridor(回廊)・Polygon・PolylineCorridor・PolylinePolygon 形式も使用できます。

代替ルートと大型車両制限

MaxAlternatives に 0〜5 を設定すると、最大5本の代替ルートをレスポンスに含めます。TravelMode: "Truck" を指定した場合は、TravelModeOptions.Truck で車両諸元と積載危険物を詳細に指定できます。

"TravelMode": "Truck",
"TravelModeOptions": {
  "Truck": {
 "GrossWeight": 40000,
 "Height": 4200,
 "Width": 2550,
 "Length": 16500,
 "HazardousCargos": ["Flammable"],
 "TunnelRestrictionCode": "B"
  }
}

TunnelRestrictionCode は ADR 協定のトンネル制限カテゴリ(A〜E)に対応しており、欧州向け輸送ルートの法規制を考慮したルーティングを実現します。最大ウェイポイント数は Origin・Destination 含めて25地点(Waypoints 配列は最大23件)です。デフォルト TPS は 20 req/sec(最大 40 まで引き上げ可能)です。

4-2. ルートマトリクスとWaypoint最適化 (多拠点配送)

CalculateRouteMatrix — 全対全コスト行列

複数の出発地と複数の目的地間の所要時間・距離を一括算出する API です。物流拠点の配置最適化・タクシー配車のマッチング・デマンドレスポンス輸送など、「全組み合わせのコストを一度に取得したい」場面で利用します。

エンドポイント: POST https://routes.geo.{region}.amazonaws.com/v2/route-matrix

{
  "Origins": [
 {"Position": [139.69, 35.68]},
 {"Position": [139.71, 35.70]},
 {"Position": [139.73, 35.74]}
  ],
  "Destinations": [
 {"Position": [135.50, 34.69]},
 {"Position": [136.90, 35.16]}
  ],
  "RoutingBoundary": {
 "Geometry": {
"BoundingBox": [135.0, 34.0, 140.5, 36.5]
 }
  },
  "DepartureTime": "2024-12-23T09:00:00Z"
}

RoutingBoundary.Geometry を指定した場合の上限は次のとおりです。

条件最大 Origins最大 Destinations最大マトリクスサイズ
GrabMaps 以外500500160,000
GrabMaps (ap-southeast-1/5)350350122,500
無制限モード (Unbounded)151001,500

無制限モード(RoutingBoundary.Unbounded: true)は境界ボックスを指定しない代わりに件数制限が厳しくなります。料金は Origins × Destinations の総ルート数ベースで課金されます。デフォルト TPS は 5 req/sec(最大 10)です。

OptimizeWaypoints — TSP 型 Waypoint 最適化

複数の配送先を巡回する最適な訪問順序を算出する API です。旧 API には存在しない機能で、Enhanced Routes API での新規追加です。内部的に巡回セールスマン問題(TSP: Travelling Salesman Problem)の近似解法を使用し、指定した最適化目標(最短時間または最短距離)に最も近い訪問順序を返します。

エンドポイント: POST https://routes.geo.{region}.amazonaws.com/v2/optimize-waypoints

{
  "Origin": {"Position": [139.69, 35.68]},
  "Destination": {"Position": [139.69, 35.68]},
  "Waypoints": [
 {"Position": [139.70, 35.72], "Id": "stop_a"},
 {"Position": [139.65, 35.66], "Id": "stop_b"},
 {"Position": [139.73, 35.74], "Id": "stop_c"},
 {"Position": [139.67, 35.71], "Id": "stop_d"}
  ],
  "OptimizeSequencingFor": "FastestRoute"
}

DestinationOrigin と同じ座標に設定することで、出発地に戻るループ型の配送最適化が可能です。

最大 Waypoint 数はティアと制約条件によって異なります。

ティア制約最大 Waypoints境界ボックス周囲長
Advanced制約なし30≤200km
Premium制約なし50≤500km
AdvancedAccessHours/AppointmentTime 等あり20≤200km
PremiumAccessHours/AppointmentTime 等あり20≤500km

Before フィールドを使うと特定 Waypoint の訪問順を部分的に固定できます。たとえば「冷凍品の配送先は常温品より先に訪問」といった業務制約も表現可能です。

多拠点配送パイプラインの設計パターン

OptimizeWaypoints で最適順序を得たうえで、CalculateRoutes に渡してターンバイターン案内と詳細所要時間を取得するパターンが実務では一般的です。

import boto3

geo_routes = boto3.client('geo-routes')
depot = [139.69, 35.68]
stops = [[139.70, 35.72], [139.65, 35.66],
[139.73, 35.74], [139.67, 35.71]]

# Step1: 訪問順序最適化
opt = geo_routes.optimize_waypoints(
 Origin={"Position": depot},
 Destination={"Position": depot},
 Waypoints=[{"Position": p, "Id": str(i)} for i, p in enumerate(stops)],
 OptimizeSequencingFor="FastestRoute"
)

# Step2: 最適化済み順序でルート詳細を取得
ordered = [w["Position"] for w in opt["OptimizedWaypoints"]]
route = geo_routes.calculate_routes(
 Origin={"Position": depot},
 Destination={"Position": depot},
 Waypoints=[{"Position": p} for p in ordered],
 LegAdditionalFeatures=["TravelStepInstructions", "Summary"]
)

デフォルト TPS は 5 req/sec(最大 10)です。

4-3. Isoline (到達圏) と通行料金計算

CalculateIsolines — 到達圏ポリゴン生成

出発地から指定した時間・距離内に到達可能なエリアをポリゴンとして返す API です。デリバリーの配送可能エリアの可視化・店舗商圏分析・緊急車両の到達圏把握・公共施設のカバレッジ評価などに活用されます。旧 API では提供されていなかった機能で、Enhanced Routes API での新規追加です。

エンドポイント: POST https://routes.geo.{region}.amazonaws.com/v2/isolines

時間ベース Isoline(前方向)

{
  "Origin": {"Position": [139.69, 35.68]},
  "Thresholds": {
 "Time": [900, 1800, 2700]
  },
  "TravelMode": "Car",
  "OptimizeIsolineFor": "BalancedCalculation",
  "IsolineGeometryFormat": "Simple"
}

Thresholds.Time は秒単位の配列で、1リクエストに最大5値まで指定できます。上記例では 15分・30分・45分の3つの到達圏ポリゴンがまとめて返されます。IsolineGeometryFormat: "Simple" を指定すると座標配列形式で返されるため、GeoJSON ポリゴンへの変換が容易になります。

距離ベース Isoline

{
  "Origin": {"Position": [139.69, 35.68]},
  "Thresholds": {
 "Distance": [5000, 10000, 20000]
  },
  "TravelMode": "Truck"
}

Thresholds.Distance はメートル単位です。5km・10km・20km 圏を1リクエストで取得できます。

逆方向 Isoline(到達可能な出発地エリアを算出)

Origin ではなく Destination を指定すれば、「どこから出発すれば〇分以内でここへ到着できるか」という逆方向計算になります。ArrivalTime と組み合わせることで、特定の時刻までに目的地に到着できる出発エリアを特定できます。オンデマンド交通や緊急配車のサービスエリア設計で有効です。

OptimizeIsolineFor — 精度と速度のトレードオフ

特徴
AccurateCalculation高精度優先。計算時間が最も長い
BalancedCalculation精度と速度のバランス型(デフォルト)
FastCalculation速度優先。精度はやや低下

ダッシュボードへのリアルタイム表示には FastCalculation、レポート生成など非同期用途には AccurateCalculation が適しています。TravelMode の Transit・Intermodal は Isolines 非対応です。

料金体系の注意点

Isolines は API コール数ではなく、レスポンスに含まれるアイソライン件数ベースで課金されます。1リクエストで閾値を3つ指定した場合、3件分の課金が発生します。ティアは時間・距離閾値で決まります。

ティア時間閾値距離閾値
Advanced≤60分(3,600秒)≤100km(100,000m)
Premium≤180分(10,800秒)≤300km(300,000m)

通行料金 (Toll Cost) 計算

Enhanced Routes API は通行料金の見積もりにも対応しています(旧 API では非対応)。CalculateRoutes のリクエストに LegAdditionalFeatures: ["Tolls"] を追加すると、ルート上の料金所情報と通行料金の見積もりがレスポンスに含まれます。

{
  "Origin": {"Position": [139.69, 35.68]},
  "Destination": {"Position": [135.50, 34.69]},
  "DepartureTime": "2024-12-23T09:00:00Z",
  "TravelMode": "Car",
  "Tolls": {
 "Currency": "JPY"
  },
  "LegAdditionalFeatures": ["Tolls", "Summary"]
}

レスポンスの Legs[].Tolls には ETC/トランスポンダー使用時の料金(Transponders)とビネット(路線通行許可証)使用時の料金(Vignettes)が区別して返されます。Currency フィールドでローカル通貨と換算通貨の両方を取得できます。LegAdditionalFeatures: ["Tolls"] または SpanAdditionalFeatures: ["TollSystems"] を指定すると Premium ティアの課金になります。

通行料金機能は GrabMaps(ap-southeast-1/ap-southeast-5 リージョン)では非サポートです。料金の単価はリージョン・時期によって変動するため、最新の単価は必ず公式料金ページの Routes タブで確認してください。


5. Geofences & Trackers — 位置イベント駆動設計

fig05: GeofencesとTrackersのEventBridge連携フロー
fig05: GeofencesとTrackersのEventBridge連携フロー

5-1. ジオフェンス境界定義とENTER/EXITイベント

ジオフェンス(Geofence)は地図上に定義する仮想的な境界領域です。Amazon Location Serviceでは、ジオフェンスコレクション(Geofence Collection)というリソースに複数のジオフェンスを格納・管理します。アプリケーションからデバイスの位置情報を送信すると、コレクション内の全ジオフェンスと照合され、境界の通過を検知します。

ジオフェンスの形状

ジオフェンスの境界形状として、以下の3種類をサポートしています。

  • Circle(円): 中心座標と半径(メートル)を指定します。配送拠点や店舗周辺など、単純な円形エリアの定義に適しています。
  • Polygon(ポリゴン): 複数の頂点座標を結ぶ多角形の境界を定義します。建物の敷地や行政区域など、不規則な形状のエリアに対応します。
  • MultiPolygon(マルチポリゴン): 複数のポリゴンをひとつのジオフェンスとして管理します。飛び地を含む複合エリアの定義に使用します。

ENTER/EXITイベントの仕組み

ジオフェンスの重要な特性は、デバイスの位置が境界を越えた瞬間にのみイベントが発生する点です。デバイスがジオフェンス内に滞在している間は継続的な通知が届くわけではなく、ENTER(進入)とEXIT(退出)という状態変化のタイミングでのみイベントが生成されます。通常の位置更新頻度より大幅に少ない頻度でのイベント処理が可能になります。

デバイスごとの状態管理として、Amazon Location Serviceは各デバイスの直前の位置情報を最大30日間保持します。最後の位置更新から30日を経過した場合、次の位置更新は「初回更新」として扱われ、以下の挙動になります。

  • ジオフェンス内に位置する場合: ENTERイベントが発生します
  • ジオフェンス外に位置する場合: イベントは発生しません(EXITは発生しない点に注意)

この初回更新ルールは、トラッカーとジオフェンスコレクションを連携後の最初の位置評価にも適用されます。連携設定以前に位置更新があったデバイスでも、連携後の初回評価は新規として処理されます。

ジオフェンスイベントはデフォルトでEventBridgeへ送出

ENTER/EXITのジオフェンスイベントは、追加設定なしに自動的にAmazon EventBridgeへ送出されます。ジオフェンスコレクションとトラッカーを連携させると同時に、境界通過イベントがEventBridgeに流れ始めます。EventBridgeのルールとターゲット(Lambda・SNS・SQSなど)を設定するだけで、境界通過イベントへの即時対応が可能です。

ジオフェンスイベントのスキーマ

EventBridgeに送出されるジオフェンスイベントのdetail-type"Location Geofence Event"です。detailフィールドにはEventTypeENTERまたはEXIT)、GeofenceIdDeviceIdSampleTimePosition(経度・緯度の配列)、任意のAccuracyGeofencePropertiesPositionPropertiesが含まれます。

{
  "detail-type": "Location Geofence Event",
  "source": "aws.geo",
  "detail": {
 "EventType": "ENTER",
 "GeofenceId": "warehouse-gate-A",
 "DeviceId": "truck-001",
 "SampleTime": "2024-06-01T08:30:00Z",
 "Position": [139.6917, 35.6895],
 "Accuracy": { "Horizontal": 10.0 },
 "GeofenceProperties": { "Type": "LoadingDock" },
 "PositionProperties": { "VehicleType": "Truck" }
  }
}

EventBridgeの仕様として、同一イベントは複数回配信される場合があります。idフィールドを使って重複処理を防ぐ冪等性を実装してください。

5-2. Trackersによるデバイス位置追跡と位置履歴

トラッカー(Tracker)は複数デバイスの位置情報を一元管理するリソースです。位置情報の書き込み・照会・履歴管理に加え、ジオフェンスコレクションと連携させることで、位置更新のたびに自動的にジオフェンスを評価できます。

位置情報の書き込みAPI

デバイスの位置情報はSDKまたはAPIを通じてトラッカーに送信します。

  • BatchUpdateDevicePosition: 複数デバイスの位置情報を一括送信するAPIです。1リクエストで最大10台のデバイスを更新できます。本番環境ではこのAPIでバッチ処理することで、APIコール数とコストを最適化します。
  • UpdateDevicePosition: 単一デバイスの位置情報を更新します。テストやシンプルな用途に向いています。

位置情報には座標(経度・緯度)とタイムスタンプに加え、速度・方向・タイヤ空気圧・エンジン温度などのメタデータをキー・バリュー形式(最大3フィールド)で付与できます。このメタデータはEventBridgeイベントのPositionPropertiesとして伝播されるため、下流のLambdaでのルーティングに活用できます。

トラッカーとジオフェンスコレクションの連動

トラッカーに1つ以上のジオフェンスコレクションを関連付けると、位置更新のたびに自動的にジオフェンス評価が実行されます。連携はコンソールまたはAPIで設定します。複数のジオフェンスコレクションを同一トラッカーに関連付けることも可能で、用途別のコレクション分離(配送エリア用・禁止区域用など)を実現できます。

位置フィルタリング(3種類)

GPS測定のジッター(微細な位置変動)や高頻度の位置更新から生じるノイズを除去するために、トラッカーは位置フィルタリング機能を提供しています。フィルタリングにより、保存される位置情報数とジオフェンス評価回数を削減し、コストを最適化できます。

フィルタリング方式仕組み推奨シナリオ
AccuracyBased直前の位置との距離が測定精度の合算値未満の更新を除外(保存・評価ともにスキップ)GPS/モバイルデバイスのように精度値を提供できる場合
DistanceBased直前の位置から30m未満の移動では更新を除外(保存・評価ともにスキップ)精度値を提供できないデバイスでジッターを抑制したい場合
TimeBased(デフォルト)30秒以内に受信した更新は保存をスキップするが、ジオフェンス評価は全更新に対して実施更新頻度が高く(30秒未満の間隔)、ほぼリアルタイムのジオフェンス評価が必要な場合

AccuracyBased方式では、2つの連続する位置更新の精度が5mと10mの場合、デバイスの移動距離が15m(合算)未満なら2番目の更新が除外されます。除外された更新はジオフェンス評価も行われず、保存もされません。

TimeBased方式を使用する場合のコストに注意してください。トラッカーが2つのジオフェンスコレクションに関連付けられている場合、5秒ごとに位置更新を送信すると、1台のデバイスあたり1時間に720件の位置更新リクエストと1,440件のジオフェンス評価が課金対象となります。更新頻度とフィルタリング設定はコストに直接影響するため、適切な設計が重要です。

位置履歴の照会

トラッカーに蓄積された位置履歴は以下のAPIで照会できます。

  • GetDevicePosition: 指定デバイスの最新位置情報を取得します。リアルタイムダッシュボードでの現在地表示に使用します。
  • GetDevicePositionHistory: 指定デバイスの位置履歴を時間範囲で取得します。ページネーション対応で、長期間の追跡履歴を分割取得できます。
  • ListDevicePositions: トラッカー内の全デバイスの最新位置情報を一覧取得します(1リクエストで最大100デバイス)。フリート管理の一覧表示に適しています。

データ保護

トラッカーに保存される位置情報は、デフォルトではAWS所有キーで暗号化されます。より高いセキュリティ要件がある場合は、AWS KMSで管理するカスタマーマネージドキー(CMK)を追加の暗号化レイヤーとして設定できます。

5-3. EventBridge連携による通知・自動化

ジオフェンスENTER/EXIT vs トラッカー位置更新イベント — 重要な区別

Amazon Location ServiceとEventBridgeの統合において、最も混同しやすいのが「どのイベントがデフォルトで送出されるか」という点です。ここを誤解すると、期待していたイベントが届かない、あるいは想定外のイベントが届くという問題が発生します。

イベント種別EventBridge送出必要な設定
ジオフェンスENTER/EXITイベントデフォルトで自動送出追加設定不要
トラッカー位置更新イベント(UPDATE)オプトイントラッカー設定で明示的に有効化が必要

ジオフェンスのENTER/EXITイベントは、ジオフェンスコレクションとトラッカーを連携させた時点から自動的にEventBridgeに送出されます。一方、デバイスの位置更新そのもの(フィルタリング済みのUPDATEイベント)をEventBridgeで受け取るには、トラッカーリソースへの明示的なオプトインが必要です。

トラッカー位置更新イベントのオプトイン方法

AWS CLIで既存トラッカーの位置更新イベントを有効化するには、以下のコマンドを実行します。

aws location update-tracker \
  --tracker-name MyFleetTracker \
  --event-bridge-enabled

無効化するにはコンソールまたはUpdateTracker APIを使用します(CLIの--event-bridge-enabledフラグは有効化のみに対応)。トラッカー作成時に有効化する場合は、CreateTracker APIのEventBridgeEnabledパラメータをtrueに設定します。

EventBridgeルールの設定

ジオフェンスイベント用のルールパターン(ENTERのみを対象にする例)を以下に示します。

{
  "source": ["aws.geo"],
  "detail-type": ["Location Geofence Event"],
  "detail": {
 "EventType": ["ENTER"]
  }
}

トラッカー位置更新イベント用のルールパターンは以下のとおりです。

{
  "source": ["aws.geo"],
  "detail-type": ["Location Device Position Event"]
}

位置更新イベント(UPDATE)は単一のEventTypeのみを持つため、EventTypeによる詳細フィルタリングは不要です。ENTERとEXITの両方を処理する場合は"detail"EventType指定を省略します。全Amazon Locationイベントをキャプチャする場合はsource: ["aws.geo"]のみを指定します。

カスタムプロパティによるイベントフィルタリング

ジオフェンスにはカスタムプロパティ(GeofenceProperties)を設定でき、EventBridgeルールでの絞り込みに活用できます。荷役ドックへの進入のみを処理対象にする場合は以下のように設定します。

{
  "source": ["aws.geo"],
  "detail-type": ["Location Geofence Event"],
  "detail": {
 "EventType": ["ENTER"],
 "GeofenceProperties": {
"Type": "LoadingDock"
 }
  }
}

デバイス側のメタデータ(PositionProperties)と組み合わせることで、特定の車両タイプからのイベントのみをLambdaに渡す細かな制御も可能です。1つのEventBusに作成できるルール数は最大300件です。複数のジオフェンスコレクションやトラッカーを運用する大規模システムでは、ルール数の上限に注意してください。

Lambda統合による自動化の実装例

EventBridgeルールのターゲットにAWS Lambdaを設定することで、ジオフェンスイベント発生時の処理を自動化できます。配送管理システムでは、ドライバーが倉庫のジオフェンスに進入(ENTER)した際にSNS経由でプッシュ通知を送信し、退出(EXIT)時に荷物スキャン記録をDynamoDBに書き込む、といったユースケースが代表的です。同一イベントは複数回配信される場合があるため、Lambda側ではidフィールドによる冪等性処理を推奨します。

コストに関する注意点(リージョン・時期により変動)

Amazon Location Serviceの料金はリクエスト数に基づく従量課金制です。ジオフェンス評価はデバイス位置評価1件あたり、位置更新はデバイス位置更新1件あたりで課金されます。具体的な単価はリージョンや時期によって変動するため、実装前に公式料金ページで最新の料金を必ず確認してください。ボリュームに応じた段階割引も提供されており、月間使用量が増えるにつれて単価が下がる仕組みになっています。新規AWSアカウントには無料利用枠が設けられています(詳細は公式料金ページを参照)。


6. 認証・運用・コスト

6-1. 認証方式の選定

Amazon Location Service には3つの認証方式があります。フロントエンドとバックエンドで適切な方式を選ばないと、セキュリティ上の問題やアクセス拒否エラーが発生します。

方式1: API キー(フロントエンド向け・読み取り系限定)

API キーは Maps / Places / Routes の読み取り系 API に限定して利用できる認証方式です。最も重要な制約として、リソースの作成・変更・削除はできません。Geofence コレクションや Tracker の作成・デバイス位置の書き込みなど、書き込み系の操作には API キーを使用できません。

API キーの主な特徴は以下のとおりです。

  • 発行場所: Amazon Location Service コンソール、または CreateKey API で作成します。
  • スコープ制限: 特定の API(例: geo:GetTile)に絞って権限を付与できます。
  • ドメイン制限: AllowReferers パラメータで許可する HTTP Referer を制限でき、特定ドメインからのみ利用可能にできます。
  • 有効期限: 任意の有効期限を設定できます。期限なしの場合は手動でローテーションが必要です。
  • パフォーマンス: Cognito と比較してレイテンシが低くなります。同一タイルのキャッシュが有効になるためです。

API キーは URL クエリパラメータ(?key=xxx)またはリクエストヘッダーで渡します。ブラウザの JavaScript で直接使用できますが、GitHub などに誤ってコミットしないよう環境変数や Secrets Manager で管理してください。

// MapLibre GL JS での API キー使用例
import maplibregl from 'maplibre-gl';

const map = new maplibregl.Map({
  container: 'map',
  style: `https://maps.geo.ap-northeast-1.amazonaws.com/v2/styles/Standard/descriptor?key=${API_KEY}&color-scheme=Light`,
  center: [139.6917, 35.6895],
  zoom: 12,
});

方式2: Amazon Cognito Identity Pools(フロントエンド向け・リソース操作可)

Cognito Identity Pools は、モバイルアプリや SPA (Single Page Application) で未認証ゲストアクセスまたは認証済みユーザーアクセスを提供する方式です。API キーと異なり、Tracker への位置書き込みや Geofence コレクションの作成など、書き込み系の操作が可能です。

Cognito Identity Pools を使う場合、以下の2パターンがあります。

  • 未認証ゲストアクセス: Identity Pool の未認証ロールに Location Service の権限を付与します。デバイス追跡アプリでユーザーログイン不要で位置送信させる場合などに使います。
  • 認証済みアクセス: Cognito User Pools / OIDC プロバイダーと組み合わせ、認証済みユーザーにより広い権限を付与します。

Cognito の利点は、IAM ポリシーで細かいアクセス制御ができることです。例えば、認証済みユーザーは自分のデバイス ID のみ位置更新できる、というポリシーを ${cognito-identity.amazonaws.com:sub} 変数で実装できます。

{
  "Effect": "Allow",
  "Action": "geo:BatchUpdateDevicePosition",
  "Resource": "arn:aws:geo:ap-northeast-1:123456789012:tracker/fleet-tracker",
  "Condition": {
 "StringEquals": {
"geo:DeviceId": "${cognito-identity.amazonaws.com:sub}"
 }
  }
}

方式3: IAM ロール(バックエンド・サーバーサイド向け)

Lambda 関数・EC2 インスタンス・ECS タスクからアクセスする場合は IAM ロールを使います。実行環境にアタッチされた IAM ロールの権限が自動的に使用されるため、認証情報の管理が不要です。

import boto3

location_client = boto3.client('location', region_name='ap-northeast-1')

# Geofence コレクションの作成(API キーでは不可、IAM ロールが必要)
response = location_client.create_geofence_collection(
 CollectionName='delivery-zones',
 Description='配送エリア定義',
)

認証方式の選定フロー

ユースケース推奨方式
SPA / モバイルアプリで地図表示・検索・ルート計算のみAPI キー
モバイルアプリでデバイス位置を Tracker に書き込むCognito Identity Pools
ユーザー個人の行動データを分離管理したいCognito + 認証済みロール
Lambda / EC2 からバックエンド処理で利用IAM ロール
Geofence / Tracker のリソース管理(作成・削除)IAM ロール(管理者権限)

6-2. 料金体系(リクエスト課金と無料枠)

Amazon Location Service は事前コミットメント不要のリクエスト従量課金です。機能ごとに課金単位が異なります。

無料枠(新規 AWS アカウントから3ヶ月間)

アカウント開設後3ヶ月間は以下の月次無料枠が適用されます。

機能無料枠(月次)
Maps — タイルリクエスト(GetTile)500,000 リクエスト
Maps — 静的地図画像(GetStaticMap)5,000 リクエスト
Places — 検索・Autocomplete / Suggest10,000 リクエスト
Places — ジオコーディング / 逆ジオコーディング20,000 リクエスト
Routes — ルート計算(CalculateRoutes)10,000 リクエスト
Trackers — デバイス位置書き込み200,000 件
Trackers — バッチ位置取得10,000 リクエスト
Geofences — 位置評価200,000 件
Geofences — CRUD 操作10,000 リクエスト

なお、2025年7月15日以降に開設した新規アカウントは、最大 200 ドルの AWS 無料枠クレジットが追加で適用され、6ヶ月間有効です。

料金体系の構造(リクエスト種別ごとの課金)

無料枠を超えた場合、機能ごとに以下の料金構造が適用されます。具体的な単価はリージョン・時期により変動するため、必ず Amazon Location Service 料金ページ の最新値を確認してください

Maps API

地図タイルリクエスト(GetTile)はリクエスト数に応じた従量課金です。GetGlyphsGetStyleDescriptorGetSprites は無料です。地図スクロール時には複数タイルが同時リクエストされるため、予想より多くなりがちです。

Places API

料金は「Label / Core / Advanced / Stored」の4段階のバケットがあり、リクエストで指定するレスポンスフィールド(営業時間・連絡先などのリッチ詳細)によって課金バケットが変わります。基本的なジオコーディングのみであれば Label バケット(最低単価)が適用されます。

Routes API

CalculateRoutes は「Core / Advanced / Premium」の3段階です。移動手段(Car・Truck・Pedestrian は Core、Scooter は Advanced)や通行料金計算の有無(Premium)で課金バケットが変わります。多拠点配送の OptimizeWaypoints は「Advanced / Premium」の2段階で、ウェイポイント数や対象エリア規模で分類されます。到達圏計算 CalculateIsolines は「Advanced / Premium」の2段階です。

Trackers と Geofences

Tracker は書き込まれたデバイス位置数、位置読み取りリクエスト数で課金されます。Geofences は位置評価回数(Tracker がジオフェンスと照合する処理)と CRUD 操作数で課金されます。

月次 5,000 ドル超の大口割引

月次利用額が 5,000 ドルを超える場合、ボリュームディスカウントが適用されます。大規模な車両管理システムや高トラフィックなコンシューマーアプリでは、AWS アカウントチームへの問い合わせを検討してください。

6-3. コスト最適化と運用監視

コスト最適化パターン1: 地図タイルのキャッシュ

地図タイルは HTTP キャッシュヘッダーを持ちます。ブラウザのデフォルトキャッシュを活用するだけでも、同一エリアの再表示では追加リクエストが発生しません。Service Worker を使ったオフラインキャッシュを実装すると、モバイルアプリでのリクエスト数をさらに削減できます。

API キーを使用した場合、リクエストパスが同一であれば CDN レベルでのキャッシュが有効になるため、Cognito 認証より全体的なリクエスト数が少なくなります。

コスト最適化パターン2: Places API のフィールドフィルタリング

Places API のレスポンスフィールドを AdditionalFeatures パラメータで制限することで、リッチ詳細(営業時間・電話番号・カテゴリ等)が不要な場合に課金バケットを下げられます。住所検索のみが目的であれば、不要なフィールドをリクエストから除外してください。

# 必要最小限のフィールドのみ指定(Label バケット適用)
response = location_client.geocode(
 QueryText='東京都千代田区霞が関1-1-1',
 MaxResults=5,
 # AdditionalFeatures を指定しない = 基本フィールドのみ
)

コスト最適化パターン3: Tracker の位置更新頻度と距離フィルタ

デバイス追跡では、更新頻度を闇雲に上げると位置書き込みコストが線形に増加します。Amazon Location Service の Tracker は PositionFiltering 設定で位置フィルタリングを制御できます。

  • TimeBased: 30秒以内の連続更新を自動的に1回にまとめます。
  • DistanceBased: 前回位置から 30m 以上移動した場合のみ記録します(静止中の不要更新を排除)。
  • AccuracyBased: GPS 精度に基づいてフィルタリングします。

配送追跡アプリでは DistanceBased が効果的で、信号待ちや駐車中の無駄なリクエストを削減できます。

# Tracker 作成時のフィルタ設定
response = location_client.create_tracker(
 TrackerName='delivery-tracker',
 PositionFiltering='DistanceBased',  # 30m未満の移動は記録しない
 Description='配送車両追跡',
)

コスト最適化パターン4: 無料枠の段階的活用

3ヶ月の無料枠期間を開発・検証フェーズとして積極活用してください。本番リリース前に実際のトラフィックパターンを計測し、月次コストを見積もった上でサービスインできます。

Geofence の位置評価は Tracker がデバイス位置を書き込むたびに自動実行されます。ジオフェンスの数と更新頻度の積が評価回数になるため、ジオフェンスのアクティブ件数管理も重要です。使用頻度が低い期間限定のジオフェンス(例: イベント会場の一時的なエリア)は、期間終了後に削除してください。

CloudWatch による運用監視

Amazon Location Service のメトリクスは CloudWatch に自動的に送信されます。監視すべき主要メトリクスは以下のとおりです。

メトリクス用途
ResourceCountTracker / Geofence コレクションのリソース数監視
DevicePositionsReceivedTracker への位置書き込み数(コスト予測に使用)
PositionEvalCountGeofence の位置評価回数(コスト予測に使用)
SystemErrorsAPI エラー数の異常検知

料金の予期せぬ急増を検知するため、AWS Budgets でアラートを設定してください。クライアント側のバグで毎秒ポーリングが走るようなケースでも、早期に検知できます。

# AWS Budgets でのコストアラート設定例(boto3)
import boto3

budgets_client = boto3.client('budgets', region_name='us-east-1')

budgets_client.create_budget(
 AccountId='123456789012',
 Budget={
  'BudgetName': 'location-service-monthly',
  'BudgetLimit': {'Amount': '100', 'Unit': 'USD'},
  'TimeUnit': 'MONTHLY',
  'BudgetType': 'COST',
  'CostFilters': {'Service': ['Amazon Location Service']},
 },
 NotificationsWithSubscribers=[{
  'Notification': {
'NotificationType': 'ACTUAL',
'ComparisonOperator': 'GREATER_THAN',
'Threshold': 80,  # 予算の80%で通知
'ThresholdType': 'PERCENTAGE',
  },
  'Subscribers': [{'SubscriptionType': 'EMAIL', 'Address': 'ops@example.com'}],
 }],
)

IAM アクセス権限の最小化

Lambda 関数や EC2 インスタンスに付与する IAM ポリシーは最小権限の原則に従ってください。全機能に geo:* を付与せず、実際に使用する API アクション(例: geo:SearchPlaceIndexForText, geo:CalculateRoute)だけを許可します。未使用の API への誤ったリクエスト(コードバグ等)が課金に結びつくリスクを低減できます。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": [
  "geo:Geocode",
  "geo:SearchNearby",
  "geo:CalculateRoutes"
],
"Resource": "*"
 }
  ]
}

料金の最新単価はリージョン・時期によって変動します。本番環境のコスト計画を立てる際は、Amazon Location Service 料金ページ で当日の単価を確認した上で見積もりしてください。


7. 実戦統合パターン — 移行設計と物流・店舗E2E

fig06: Google Maps Platform移行E2Eパターン
fig06: Google Maps Platform移行E2Eパターン

Amazon Location Serviceの実戦統合は、Google Maps Platformからの移行設計・配送物流トラッキング基盤・店舗検索E2Eの3パターンが代表的です。イベント駆動型アーキテクチャと他AWSサービスの組み合わせにより、スケーラブルかつコスト最適化されたシステムを構築できます。

7-1. Google Maps Platformからの移行設計 (Migration SDK)

Migration SDKの概要:

AWS Migration SDK for Amazon Location Serviceは、Google Maps Platform(GMP)のJavaScript APIをAmazon Location Serviceへ段階的に移行するためのオープンソースライブラリです。2025年7月の拡張更新により、Maps・Places・Routes・Geocodingの主要APIをカバーし、既存のGMPコードへの変更を最小限に抑えた移行を実現します。

npmパッケージとして提供されており、GMPのAPIキーをAmazon Location Serviceの認証(APIキーまたはCognito Identity Pools)に置き換えます。

// 移行前: Google Maps Platform
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_API_KEY"></script>

// 移行後: Amazon Location Service Migration SDK
// npm install @aws/amazon-location-migration-sdk
import { MigrationMap, MigrationGeocoder } from "@aws/amazon-location-migration-sdk";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";

const credentials = fromCognitoIdentityPool({
  identityPoolId: "ap-northeast-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  clientConfig: { region: "ap-northeast-1" }
});

// google.maps.Map と互換の MigrationMap
const map = new MigrationMap(document.getElementById("map"), {
  center: { lat: 35.6812, lng: 139.7671 },
  zoom: 14,
  region: "ap-northeast-1",
  credentials,
  mapStyle: "Standard"
});

// google.maps.Geocoder と互換の MigrationGeocoder
const geocoder = new MigrationGeocoder({ region: "ap-northeast-1", credentials });
geocoder.geocode({ address: "東京駅" }, (results, status) => {
  if (status === "OK") {
 map.setCenter(results[0].geometry.location);
  }
});

対応API範囲(2025年7月時点):

GMP APIMigration SDK対応クラスAmazon Location Service API
google.maps.MapMigrationMapMaps – GetStaticMap / GetTile
google.maps.GeocoderMigrationGeocoderGeocode / ReverseGeocode
google.maps.DirectionsServiceMigrationDirectionsServiceCalculateRoutes
google.maps.DistanceMatrixServiceMigrationDistanceMatrixServiceCalculateRouteMatrix
google.maps.places.PlacesServiceMigrationPlacesServiceSearchText / SearchNearby / GetPlace
google.maps.places.AutocompleteMigrationAutocompleteAutocomplete / Suggest
google.maps.MarkerMigrationMarkerMapLibre GL JS Markerへのマッピング
google.maps.InfoWindowMigrationInfoWindow同上

2025年7月拡張ではDirectionsRendererDistanceMatrixServiceのサポートが追加され、ルート表示と距離行列計算のコード互換性が大幅に向上しました。DistanceMatrixServiceはAmazon Location ServiceのCalculateRouteMatrixへマッピングされます。

段階移行手順(推奨フロー):

移行は一括切り替えでなく、機能単位の段階的アプローチを推奨します。

  1. 使用APIの棚卸: プロジェクト内のGMP APIコールをリストアップします。grep -r "google\.maps\." src/ で使用箇所を一覧化するのが効率的です。
  2. Migration SDKの導入: パッケージをインストールし、Google MapsスクリプトタグをSDKのimport文に置き換えます。
  3. 認証設定: Amazon Location ServiceのAPIキーまたはCognito Identity Poolsを設定します。フロントエンドからの直接アクセスにはAPIキーが簡単ですが、Trackerへの書き込みを伴う場合はCognitoを選択します。
  4. 単体テスト: 移行した各コンポーネント(地図表示・ジオコーディング・ルート計算・場所検索)を個別にテストします。データプロバイダーがGMPと異なるため、地物名・住所表記は変わる場合があります。
  5. 段階的ロールアウト: フィーチャーフラグを用いて一部ユーザーにAmazon Location Service版を提供し、問題なければ全体に展開します。

コスト比較(GMP vs Amazon Location Service):

機能Google Maps Platform(目安)Amazon Location Service(目安)
地図表示(Dynamic Maps)$7.00/1,000ロード$0.04〜0.08/1,000タイル
Geocoding$5.00/1,000リクエスト$0.40〜1.00/1,000リクエスト
Directions$5.00/1,000リクエスト$0.50〜0.60/1,000リクエスト
Places Nearby Search$17.00/1,000リクエスト$0.50〜1.50/1,000リクエスト

料金はリージョン・時期・利用量によって変動します。実際の見積もりは公式料金ページ(aws.amazon.com/location/pricing/)の当日値で確認してください。月間APIコール数が多いほど移行による費用削減効果が大きくなります。

移行時のよくある落とし穴:

  • PlaceId互換性なし: GMPのPlace IDはAmazon Location ServiceのPlaceIdと互換性を持ちません。DBに保存済みのGMP Place IDは移行後に再取得が必要です。
  • 地物名・住所表記の差異: データプロバイダーがGMPと異なるため、施設名・住所の表記は変わる場合があります。QAテスト時に代表的な住所での検索結果を比較確認してください。
  • 地図スタイルの違い: Amazon Location ServiceのデフォルトスタイルはGMPとデザインが違います。カスタムスタイルを使用している場合はMapLibre GL JSのスタイル定義の更新が必要です。
  • Geocodingの精度差: 地域によってはGMPとAmazon Location Serviceで精度差が出る場合もあります。番地レベルの精度が重要なユースケースでは事前検証を推奨します。

7-2. 配送・物流トラッキング基盤のE2E設計

配送・物流業務では、ドライバーのデバイス位置情報をリアルタイムに追跡し、倉庫・顧客宅などのジオフェンス境界を越えたタイミングで自動通知するパイプラインが求められます。Trackers・Geofences・EventBridge・Lambda・DynamoDBを組み合わせることで、サーバーレスかつスケーラブルなE2Eトラッキング基盤を構築できます。

E2Eパイプライン構成:

モバイルアプリ / IoTデバイス
 │  BatchUpdateDevicePosition(30秒ごと)
 ▼
Amazon Location Service Tracker
 │  位置評価(ジオフェンス重複チェック)
 ▼
Amazon EventBridge(Location Serviceイベントバス)
 │  ENTER / EXIT イベント
 ▼
AWS Lambda(ルーティング・通知処理)
 ├─ Amazon SNS → プッシュ通知(ドライバー・顧客)
 ├─ Amazon DynamoDB → 配送ステータス更新
 └─ Amazon SES → メール通知(管理者)
import boto3
import json

location_client = boto3.client("location", region_name="ap-northeast-1")

def update_driver_position(tracker_name: str, driver_id: str,
 lat: float, lon: float, timestamp: str) -> None:
 location_client.batch_update_device_position(
  TrackerName=tracker_name,
  Updates=[{
"DeviceId": driver_id,
"Position": [lon, lat],# [経度, 緯度] の順
"SampleTime": timestamp,
"PositionProperties": {
 "vehicleType": "truck",
 "orderId": "ORD-12345"
}
  }]
 )

def lambda_handler(event: dict, context) -> dict:
 detail = event["detail"]
 event_type = detail["EventType"]  # "ENTER" or "EXIT"
 device_id = detail["DeviceId"]
 geofence_id = detail["GeofenceId"]
 position = detail["Position"]

 dynamodb = boto3.resource("dynamodb")
 table = dynamodb.Table("DeliveryStatus")

 if event_type == "ENTER" and geofence_id.startswith("depot-"):
  status = "ARRIVED_DEPOT"
 elif event_type == "ENTER" and geofence_id.startswith("customer-"):
  status = "ARRIVED_CUSTOMER"
 elif event_type == "EXIT" and geofence_id.startswith("depot-"):
  status = "DEPARTED_DEPOT"
 else:
  status = f"{event_type}_{geofence_id}"

 table.update_item(
  Key={"driverId": device_id},
  UpdateExpression="SET #st = :s, lastPosition = :p",
  ExpressionAttributeNames={"#st": "status"},
  ExpressionAttributeValues={":s": status, ":p": position}
 )

 sns = boto3.client("sns")
 sns.publish(
  TopicArn="arn:aws:sns:ap-northeast-1:123456789012:DeliveryNotifications",
  Message=json.dumps({"driverId": device_id, "status": status}),
  Subject=f"配送ステータス更新: {status}"
 )
 return {"statusCode": 200}

位置フィルタリング設定:

TrackerリソースのPositionFiltering設定で、不要な位置情報の除去と更新頻度の制御ができます。

フィルタリング設定動作推奨用途
TimeBased最終更新から30秒以上経過した場合のみ更新バッテリー消費を抑えたい場合
DistanceBased前回位置から30m以上移動した場合のみ更新停止中の不要な更新を除去
AccuracyBased位置精度が基準以上の場合のみ更新GPSドリフト対策

ジオフェンスを複数のジオフェンスコレクションに分けて管理することで、配送エリア・禁止区域・顧客宅エリアを独立したコレクションで運用できます。同一Trackerに複数コレクションを関連付けることが可能です。

7-3. 店舗検索・IoT・サーバーレス連携パターン

店舗検索のCloudFront最適化:

SearchNearbyの結果はユーザーの現在地に依存するため完全キャッシュには向きませんが、検索エリアをグリッド化してキャッシュ効率を高めるパターンが有効です。

import hashlib

def get_nearby_stores(lat: float, lon: float, radius: int = 1000) -> list:
 # 座標を小数点3桁(約100m精度)でグリッド化してキャッシュキーを生成
 grid_lat = round(lat, 3)
 grid_lon = round(lon, 3)
 cache_key = hashlib.md5(
  f"{grid_lat}:{grid_lon}:{radius}".encode()
 ).hexdigest()

 cached = get_from_cache(cache_key)
 if cached:
  return cached

 client = boto3.client("geo-places", region_name="ap-northeast-1")
 response = client.search_nearby(
  QueryPosition=[grid_lon, grid_lat],
  QueryRadius=radius,
  Filter={
"IncludeCategories": ["Retail.ShoppingMall", "Retail.Store"],
"IncludeCountries": ["JPN"]
  },
  Language="ja",
  MaxResults=50,
  AdditionalFeatures=["Details"]
 )

 stores = [
  {
"id": r.get("PlaceId"),
"name": r["Title"],
"lat": r["Position"][1],
"lon": r["Position"][0],
"distance": r.get("Distance"),
"hours": r.get("OpeningHours")
  }
  for r in response["ResultItems"]
 ]

 set_cache(cache_key, stores, ttl=3600)  # 1時間キャッシュ
 return stores

CloudFrontとAPI Gatewayを組み合わせ、グリッド化した検索結果をエッジキャッシュすることでAPIコールを最小化できます。TTLは1〜6時間が目安で、営業時間や店舗情報の変更頻度に応じて調整してください。

IoT連携パターン:

物流センターや工場内のフォークリフト・搬送ロボット等のIoTデバイスは、AWS IoT CoreとAmazon Location Serviceを連携させることで屋内外の位置情報管理を統合できます。

  1. デバイス側: AWS IoT Device SDKを使用し、位置情報をMQTTトピック(location/update/{deviceId})でpublishします。
  2. IoT Core側: IoT Rulesエンジンでトピックを受信し、Lambda関数を起動します。
  3. Lambda側: BatchUpdateDevicePositionでTrackerを更新します。
  4. EventBridge側: ジオフェンスENTER/EXITイベントを受信し、運行管理システムに通知します。

この構成では、IoT Coreのスケーリングにより1万台以上のデバイスからの同時位置情報更新に対応できます。Trackerへのバースト書き込みを平滑化するため、Lambda関数とSQSキューを経由させるアーキテクチャが推奨されます。

サーバーレス統合のベストプラクティス:

  • 位置更新の非同期化: モバイルアプリからの位置情報は直接Trackerに書き込まず、API Gateway→SQS→Lambdaの非同期パイプラインを挟むことで、アプリ側のレイテンシを低減できます。
  • Places APIのキャッシュ戦略: SearchText・SearchNearbyは同一クエリの繰り返しが多いため、DynamoDBまたはElastiCacheを活用したアプリケーションレベルのキャッシュを推奨します。TTLは店舗情報の変更頻度(通常6〜24時間)に合わせてください。
  • Geocodeのバッチ処理: 住所リストの一括ジオコーディングはLambdaの並列処理とリトライ機構で実装します。Geocode APIのAPIコール上限(デフォルト制限)に注意し、必要に応じてサービスクォータの引き上げを申請してください。
  • マルチリージョン展開: Amazon Location Serviceは東京リージョン(ap-northeast-1)で利用可能です。グローバル展開時はユーザー所在地に近いリージョンを選択し、CloudFrontのエッジキャッシュと組み合わせることでレイテンシを最小化できます。
  • 権限の最小化: Lambda関数やモバイルアプリのCognitoロールには、実際に使用するAPIアクション(例: geo:BatchUpdateDevicePositiongeo:SearchNearby)のみを許可し、geo:* の全権限付与を避けてください。

8. 詰まりポイントとアンチパターン・まとめ

8-1. 詰まりポイント

Amazon Location Serviceを本番環境へ導入する際によく発生するつまずきを8つのポイントにまとめます。

詰まりポイント1: 旧リソースベースAPIと新スタンドアロンAPIの混在

2024年10月の刷新後に書かれたチュートリアルと、それ以前の記事・ドキュメントを同時に参照すると、APIの形式が食い違います。最も多いミスは、旧APIのboto3サービス名 location と新APIの geo-maps / geo-places / geo-routes を混在させてしまうパターンです。

確認方法:
– boto3で client.get_map_tile() を呼び出していたら旧API
client.get_tile() / client.geocode() / client.calculate_routes() を呼び出していたら新API
– CloudFormationテンプレートに AWS::Location::Map リソースが定義されていたら旧リソースベース方式

対処: コードベース全体を get_map_tile / search_place_index_for_text / calculate_route で検索し、新API呼び出しに置き換えてください。

詰まりポイント2: APIキーでリソース操作をしようとして403エラー

APIキーはMaps/Places/Routesの読み取り操作にのみ使用できます。以下の操作にAPIキーを使うと AccessDeniedException が返されます。

  • BatchUpdateDevicePosition(Trackerへの位置書き込み)
  • BatchPutGeofence(ジオフェンスの追加)
  • CreateTracker / CreateGeofenceCollection(リソース作成)
  • AssociateTrackerConsumer(トラッカーへのコレクション関連付け)

「APIキーで認証しているのになぜ失敗するのか」と混乱するケースが多いです。APIキーは地図表示・住所検索・ルート計算の閲覧専用です。

対処: モバイルアプリからデバイス位置を書き込む場合はCognito Identity Pools、バックエンドからリソースを管理する場合はIAMロールを使用してください(認証方式の選定は§6参照)。

詰まりポイント3: ジオフェンスとトラッカーのイベント挙動の違い

ジオフェンスのENTER/EXITイベントとトラッカーの位置更新イベントは、EventBridgeへの送出タイミングが異なります。

  • ジオフェンス ENTER/EXIT: デバイス位置がジオフェンス境界を越えた瞬間に自動的にEventBridgeへ送出されます(AssociateTrackerConsumer でトラッカーとジオフェンスコレクションを関連付けた場合)
  • トラッカー位置更新イベント: デバイスの位置が更新されるたびにEventBridgeへイベントを送出する機能はデフォルトではオフです。有効化するには CreateTracker / UpdateTrackerEventBridgeEnabled: true を明示的に設定する必要があります

多くのケースでジオフェンスイベントのみで十分ですが、すべての位置更新をストリーミングしたい場合(リアルタイム追跡ダッシュボード等)は EventBridgeEnabled を有効化してください。コストは位置更新回数に応じて増加します。

詰まりポイント4: 料金の見積もり漏れ(GetGlyphs / GetSprites の無視)

MapLibre GL JSは地図を表示するためにタイル以外にもフォントグリフ(GetGlyphs)とスプライト画像(GetSprites)を自動的にリクエストします。これらはMapLibreが内部で発行するリクエストであり、初期表示時に複数回発生します。

見積もり時に GetTile のリクエスト数だけをカウントすると実際のコストより低く見積もってしまいます。無料枠では GetGlyphs は月250万リクエストまで無料ですが、有償枠に移行後は課金対象となります。

対処: CloudWatchメトリクスでAPIごとのリクエスト数を計測し、実際の内訳を把握した上でコスト計画を立ててください。地図スクロール・ズームごとにタイルが複数発生することも考慮に入れます。

詰まりポイント5: MapLibreのバージョン互換性問題

@aws/amazon-location-utilities-auth-helper ライブラリはmaplibre-glの特定のメジャーバージョンに対応しています。

代表的な問題パターン:
– maplibre-gl v4にアップグレードしたところ authHelper.getMapAuthenticationOptions() の返却値の形式が変わりスタイルを読み込めなくなった
– package.jsonのバージョン指定が "maplibre-gl": "*" で、自動的にv4系がインストールされた

対処: package.json でバージョンを "^3.6.0" のように固定してください。アップグレードは認証ヘルパーの互換確認後に行います。

{
  "dependencies": {
 "maplibre-gl": "^3.6.0",
 "@aws/amazon-location-utilities-auth-helper": "^1.1.0"
  }
}

詰まりポイント6: データプロバイダーの選択ミスと利用規約

Amazon Location Serviceでは機能ごとにデータプロバイダーを選択できますが、プロバイダーによって精度・対応リージョン・利用規約が異なります。

主な注意点:
Open Dataスタイルのルート計算不可: Open Dataは地図タイルのみ対応で、ルート計算・場所検索にはEsriまたはHEREが必要
GrabMapsの地域制限: GrabMapsは東南アジア特化で、日本国内のルート計算等には非対応
結果のキャッシュ・保存制限: EsriおよびHEREの利用規約では検索・ルート計算の結果を30日を超えてキャッシュ・保存することが制限されています
住所検索結果の再配布禁止: Places APIの結果をサードパーティへ再提供することは禁止されています

対処: 本番実装前に利用するプロバイダーの利用規約を確認し、データ保存・キャッシュ方針を設計してください。

詰まりポイント7: トラッカーとジオフェンスコレクションの関連付け漏れ

ジオフェンスのENTER/EXITイベントを受け取るには、トラッカーとジオフェンスコレクションを AssociateTrackerConsumer で関連付ける必要があります。この設定を忘れると、デバイス位置をいくら書き込んでもジオフェンスイベントは一切発生しません。

設定確認コマンド:

import boto3
client = boto3.client('location', region_name='ap-northeast-1')

# トラッカーに関連付けられたジオフェンスコレクションを確認
response = client.list_tracker_consumers(
 TrackerName='delivery-tracker'
)
print(response['ConsumerArns'])  # 空の場合は関連付けが未設定

対処: インフラ構築時のチェックリストに AssociateTrackerConsumer の実行を追加し、テスト環境でジオフェンスイベントが発生することを確認してからデプロイしてください。

詰まりポイント8: APIキーのドメイン制限とローカル開発の衝突

本番APIキーに AllowReferers でドメイン制限(例: https://example.com/*)を設定した場合、ローカル開発環境(http://localhost:3000)からのリクエストは 403 Forbidden になります。「本番では動くのに開発環境では動かない」という状況が発生します。

対処パターン:
– 開発用と本番用のAPIキーを分ける(開発用は AllowReferers なし)
– ローカル開発時はCognito認証に切り替える
– 環境変数でAPIキーを管理し、.env.local で開発用キーを指定する

# .env.local(Gitにコミットしない)
VITE_LOCATION_API_KEY=v1.public.dev_xxxxx...

# .env.production
VITE_LOCATION_API_KEY=v1.public.prod_xxxxx...

8-2. アンチパターン → 正解

❌ アンチパターン1: 旧リソースベースAPIをそのまま継続利用

AWS::Location::Map / AWS::Location::PlaceIndex / AWS::Location::RouteCalculator リソースをCloudFormationで定義し続けるケース。新機能(Enhanced Places / OptimizeWaypoints / CalculateIsolines等)を利用できないまま開発が進みます。

✅ 正解: 新規開発はすべてスタンドアロンAPIで実装してください。既存リソースはまず動作を維持しながら並行実装し、段階的に移行します。既存コードの検索キーワード: create_mapcreate_place_indexcreate_route_calculator(boto3)、AWS::Location::Map(CloudFormation)。


❌ アンチパターン2: APIキーをバックエンドのリソース操作に使用

Lambda関数やEC2からGeofenceを作成・削除する処理にAPIキーを使うと AccessDeniedException になります。APIキーは読み取り専用であり、書き込み系の操作には使用できません。

✅ 正解: リソース操作は実行環境(Lambda/EC2/ECS)にアタッチしたIAMロールで行います。IAMポリシーには実際に使用するアクション(geo:BatchPutGeofencegeo:BatchUpdateDevicePosition等)だけを最小権限で付与します。


❌ アンチパターン3: ジオフェンスとトラッカーを独立して管理

ジオフェンスコレクションにエリアを定義し、別のトラッカーにデバイス位置を書き込んでいるが、両者が関連付けられていないためイベントが一切発火しない状態。デバッグに時間を取られるパターンです。

✅ 正解: AssociateTrackerConsumer でトラッカーとジオフェンスコレクションを明示的に関連付けます。本番環境のテストでは、テスト用座標を送信してジオフェンスイベントがEventBridgeに届くことを必ず確認します。

import boto3
client = boto3.client('location', region_name='ap-northeast-1')

client.associate_tracker_consumer(
 TrackerName='fleet-tracker',
 ConsumerArn='arn:aws:geo:ap-northeast-1:123456789012:geofence-collection/delivery-zones'
)

❌ アンチパターン4: MapLibreのバージョンをワイルドカードで管理

"maplibre-gl": "*"

デプロイのたびに最新バージョンがインストールされ、認証ヘルパーとの互換性を突然壊すリスクがあります。CI/CDパイプラインで毎回インストールする環境では特に問題になります。

✅ 正解: キャレット(^)でマイナーバージョン固定、もしくは正確なバージョンを指定します。チームでのバージョン統一には package-lock.jsonyarn.lock をGitにコミットし、npm ci でビルドします。

"maplibre-gl": "^3.6.0",
"@aws/amazon-location-utilities-auth-helper": "^1.1.0"

❌ アンチパターン5: すべての機能に同じデータプロバイダーを使用

一度Esriを選んだからといって、ルート計算・ジオコーディング・地図タイルすべてをEsriに統一するケース。物流システムでは配送ルートの精度でHEREが上回ることもあります。一方、日本向けの住所検索や営業時間等のリッチ詳細はEsriが優れるケースもあります。

✅ 正解: 機能ごとに最適なプロバイダーを検証してから選択します。スタンドアロンAPIではリクエストごとにプロバイダーを変更できるため、「地図タイル=Esri / ルート計算=HERE」という組み合わせが可能です。本番前にA/Bテストで精度を比較することを推奨します。

8-3. まとめ

Amazon Location Serviceは2024年10月の大幅刷新により、リソース管理不要のスタンドアロン型APIに生まれ変わりました。Maps/Places/Routes/Geofences/Trackersの5機能がひとつのサービスにまとまり、APIキー・Cognito・IAMという3層の認証設計と組み合わせることで、フロントエンドから管理バックエンドまで一貫したアーキテクチャを構築できます。

本記事のポイントを振り返ります。

  • Maps: スタンドアロンAPIはboto3サービス名 geo-maps。MapLibre GL JSとの統合が標準です。バージョン固定を推奨します。
  • Places: スタンドアロンAPIはboto3サービス名 geo-places。Enhanced Places APIでリッチ詳細(営業時間・電話番号等)が取得できます。
  • Routes: スタンドアロンAPIはboto3サービス名 geo-routes。OptimizeWaypointsで多拠点配送の経路最適化ができます。
  • 認証: 読み取りにはAPIキー、書き込みにはCognito Identity Pools、バックエンドにはIAMロールを使い分けます。
  • ジオフェンス+トラッカー: AssociateTrackerConsumer で関連付けて初めてENTER/EXITイベントが発火します。位置更新イベントのEventBridge送出はオプトイン設定です。
  • コスト: 初3ヶ月の無料枠を開発・検証に活用し、CloudWatchで実際のリクエスト内訳を計測した上でコスト計画を立てます。

位置情報基盤の整備はAWSエコシステム全体の価値を高めます。EventBridgeによるジオフェンスイベントをLambdaで処理してDynamoDBに記録し、SNSで通知するサーバーレスパイプラインが追加インフラなしに構築できます。IoT CoreからTrackerへデバイス位置を流すことで、大規模なフリート管理も実現可能です。Amazon Location Serviceを核に据えることで、AWSネイティブな位置情報基盤を継続的に進化させられます。

8-4. 関連記事

IoTデバイス追跡との連携 — Amazon IoT Core本番運用
EventBridge連携の基盤 — App Integration本番運用
サーバーレス連携パターン — AWS Serverless本番運用
モバイルフロントエンド統合 — Amplify/CI CD本番運用
位置情報認証基盤 — Cognito Auth/Identity本番運用