1. 対象読者とこの記事で得られること
こんな方に向けて書きました:
- Google Mapsで美味しい飲食店を探したいエンジニア
- Bedrockで生成AIアプリを作ってみたいが、最初の一歩が分からない方
- Comprehendによる感情分析を使ってみたい方
読後に持ち帰れる技術要素:
| 技術要素 | 本記事での用途 | 汎用的に使える場面 |
|---|---|---|
ベイズ平均Bayesian average
|
レビュー信頼度補正 | ECサイト評価 推薦エンジン |
Bedrockinvoke_model
|
店舗要約の自動生成 | チャットボット ドキュメント分類 |
|
Comprehend バッチ感情分析 |
レビューの感情可視化 | カスタマーサポート分析 SNS監視 |
|
S3 + CloudFront 写真キャッシュ |
外部API写真コスト87%削減 | 画像配信最適化 CDN設計全般 |
|
DynamoDB TTLキャッシュ |
API呼び出しコスト削減 | 外部API連携全般 |
LambdaThreadPoolExecutor
|
36秒→13秒の並列化 | 複数外部API呼び出し処理全般 |
発言は個人の見解に基づくものであり、所属組織を代表するものではありません。
2. きっかけ:星4.5の店で5,000円を失った夜
先月、友達との飲み会で焼肉店を探していました。
Google Mapsで「星4.5」の店を見つけ、迷わず予約しました。しかし、実際に訪問してみると、期待とは大きくかけ離れた体験でした。レビューを改めて確認してみると、たった数件のレビューでした。冷静に見ればレビュー数の少なさに気づけたはずですが、星の数だけで判断してしまいました。
翌週、別の友達に連れて行ってもらった焼肉店は「星4.1」でしたが、レビューは数千件あり、味もサービスも期待以上でした。
この体験が出発点です。
「レビュー件数を考慮した、統計的に信頼できるランキングが欲しい」
AWSの勉強も兼ねて、「ハズレない」飲食店検索アプリを自分で作ることにしました。
![]() |
| 完成したアプリ |
3. そもそも何が問題か:数件の星4.5 vs 数千件の星4.1
以下の2店舗を比較してみてください。
| 店舗 | Google評価 | レビュー件数 |
|---|---|---|
| A | ★ 4.5 | 数件 |
| B | ★ 4.1 | 数千件 |
Google Mapsの標準UIでは店舗Aが上位に表示されます。
しかし統計学的には:
- 数件:サンプルサイズが極めて小さく、偶然高評価が集中した可能性を排除できない
- 数千件:これだけの母数で4.1を維持するには、継続的に高品質なサービスが不可欠
レビュー件数によるバイアスを統計的に補正する手法が、次に説明するベイズ平均です。
4. ベイズ平均:30秒で理解する
ベイズ平均は「サンプルサイズが小さい評価を、全体平均に引き寄せる」補正手法です。
\text{score} = \frac{C \times m + n \times r}{C + n}
| 記号 | 意味 | 本実装での値 |
|---|---|---|
| C | 仮想レビュー数(全店舗レビュー件数の中央値) | 動的計算 |
| m | 母集団平均(全店舗の平均評価) | 動的計算 |
| n | 対象店舗の実レビュー件数 | 3件 or 1,200件 |
| r | 対象店舗の実評価 | 4.5 or 4.1 |
- レビューが少ない → 全体平均に引き寄せられる(保守的な評価)
- レビューが多い → 実評価がそのまま反映される(データに基づく評価)
なぜ平均値ではなく中央値か
検索結果にはレビュー5,000件の超人気店と10件の新店舗が混在します。平均値では外れ値に引っ張られるため、中央値を使ってロバストな閾値を算出しています。
4.1 実際に計算してみる
仮に全体平均 = 3.8、中央値(仮想レビュー数)= 200
店舗Aのレビュー件数 = 3件、店舗Bのレビュー件数 = 1200件とすると:
店舗A(星4.5 / 3件)
\frac{200 \times 3.8 + 3 \times 4.5}{200 + 3} = 3.81
店舗B(星4.1 / 1,200件)
\frac{200 \times 3.8 + 1200 \times 4.1}{200 + 1200} = 4.06
結果としてランキングが逆転し、レビュー件数の裏付けがある店舗Bが上位に来ます。これが「統計的に信頼できる店」の発掘につながります。
5. アーキテクチャ:シンプルな単一Lambda構成
![]() |
| 構築したアーキテクチャ |
キャッシュの確認
キャッシュMiss時のLambda処理
5.1 技術スタック
| レイヤー | 技術 | 選定理由 |
|---|---|---|
| フロントエンド | Next.js + TypeScript | 型安全性、SSR対応 |
| スタイリング | Tailwind CSS | 高速なUI構築 |
| ホスティング | Amplify Gen 2 | Git Push連動の自動デプロイ |
| API | API Gateway (REST) | シンプルな構成 |
| ロジック | Lambda (Python) | サーバーレス、コールドスタート改善 |
| キャッシュ | DynamoDB (TTL付き) | フルマネージド、自動失効 |
| キャッシュ(写真) | S3 + CloudFront | OAI制御、30日ライフサイクル自動削除 |
| AI(要約) |
Bedrock (Claude Haiku 4.5) |
低コスト、高速、日本語対応 |
| AI(感情分析) | Comprehend | バッチ処理対応、日本語対応 |
| シークレット | SSM Parameter Store | SecureString暗号化 |
| IaC | CloudFormation | 環境の再現性、変更履歴の管理 |
5.2 なぜ単一Lambdaにしたか
当初はStep Functions + 複数Lambda構成を検討しましたが、以下の理由から採用を中止しました。
| 観点 | Step Functions | 単一Lambda(採用) |
|---|---|---|
| 実装複雑度 | 高(ステートマシン定義) | 低(直線的フロー) |
| デバッグ | ログが複数関数に分散 | CloudWatchに集約 |
| レイテンシ | Lambda間通信のオーバーヘッド | 関数内で完結 |
| コスト | Step Functions実行料金が加算 | Lambda実行料金のみ |
以上の理由から、要件に対してStep Functionsは過剰と判断し、まず動くものを最速で出してスケーラビリティが必要になった段階で分割する方針としました。
5.3 セキュリティ設計
個人開発の範疇ではありますが、最低限のセキュリティ設計を施しました。
シークレット管理
- Google Places APIキーはSSM Parameter Storeで管理
- Lambda環境変数にハードコードしない
IAM最小権限の原則
- Lambda実行ロールはDynamoDB・Bedrock・Comprehendへの必要最小限のアクセスのみ許可
- リソースARNを明示的に指定
S3アクセス制御
- CloudFront OAI(Origin Access Identity)経由のみ公開アクセスを許可
- 直接のS3 URLは外部に公開しない
CORS制御
- API Gatewayで許可オリジンをAmplifyドメインに限定
入力検証
- 駅名・ジャンルはホワイトリスト方式でバリデーション
6. つまずきポイント5選
ここからが本記事の核心です。開発中に遭遇した問題と、その解決過程を共有します。
6.1 つまずき① Google Places APIのレビュー件数制限
問題
- レビューを数十件を取得して、感情分析の精度を上げたい
- Google Places APIの検索エンドポイントは、1店舗あたり最大5件のレビューを返却
検討した選択肢:
| 選択肢 | コスト影響 | 判断 |
|---|---|---|
| Place Details APIを各店舗に追加実行 | +$0.34/検索(53%増) | ✕ コスト増が大きい |
| 5件で運用 | 現状維持 | 〇 採用 |
判断と根拠
- 5件のレビューでも感情の傾向は十分に把握できると判断
- 完璧な精度よりもコストとユーザー体験(レスポンス速度)のバランスを重視
6.2 つまずき② Bedrockのモデルリージョン問題
問題
- 東京リージョン(
ap-northeast-1)でBedrock呼び出しが失敗
# ✕ 動作しない(北米向けプレフィックス)
MODEL_ID = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
# ✕ これも動作しない
MODEL_ID = "ap.anthropic.claude-haiku-4-5-20251001-v1:0"
# 〇 東京リージョンではjpプレフィックスが必要
MODEL_ID = "jp.anthropic.claude-haiku-4-5-20251001-v1:0"
解決策
- リージョンごとにモデルIDのプレフィックスが異なる
- 以下のコマンドで利用可能なモデルを確認可能
aws bedrock list-inference-profiles \
--region ap-northeast-1 \
--query "inferenceProfileSummaries[?contains(inferenceProfileId, 'haiku')]"
6.3 つまずき③ 写真取得のskipHttpRedirect
問題
- Google Places APIで取得した写真URLにアクセスすると、302リダイレクト先のセッション付きURLが返却
- このURLはサーバーサイドでのみ有効で、クライアントブラウザからはアクセスできない
# ✕ 302リダイレクト → セッション付きURL(クライアントからアクセス不可)
url = f"https://places.googleapis.com/v1/{photo_name}/media?key={api_key}"
# 〇 skipHttpRedirect=trueでphotoUriをJSONで直接取得
url = f"https://places.googleapis.com/v1/{photo_name}/media?skipHttpRedirect=true&key={api_key}"
教訓
-
skipHttpRedirect=trueを付与しないと写真が表示されない - APIドキュメントの細部まで確認する重要性
6.4 つまずき④ S3 HeadObjectの403エラーとバケットポリシー設計
問題
# 403 Forbidden
s3.head_object(Bucket=S3_PHOTO_BUCKET, Key=s3_key)
原因
- S3のPublic Access Blockが有効な状態では、IAMポリシーだけでなくバケットポリシーにもLambdaロールを明示的に許可する必要がある
-
s3:HeadObjectというアクションはバケットポリシーに存在しない
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:role/lambda-role"},
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::bucket-name/*"
},
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::123456789012:role/lambda-role"},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::bucket-name"
}
ポイント:
-
HeadObjectはs3:GetObject権限でカバーされる(バケットポリシーにs3:HeadObjectは存在しない) - 404判定に使う場合は
s3:ListBucketをバケットレベル(/*なし)で付与する必要がある - OAI用のバケットポリシーとLambdaロール用のポリシーは別ステートメントで管理
6.5 つまずき⑤ 処理時間 36秒 → 13秒への改善
問題
- 20店舗分のBedrock呼び出しを直列処理した結果、レスポンスに36秒もかかった
# ✕ Before: 直列処理(約25秒)
for item in restaurants:
enrich_item(item)
# 〇 After: 並列処理(約8秒)
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(enrich_item, item) for item in restaurants]
for f in as_completed(futures):
f.result()
| 処理 | Before | After | 削減率 |
|---|---|---|---|
| Bedrock要約生成 | 25秒 | 8秒 | 68% |
| 写真URL取得 | 8秒 | 2秒 | 75% |
| 合計 | 36秒 | 13秒 | 64% |
教訓
- I/Oバウンドな処理(外部API呼び出し)は
ThreadPoolExecutorによる並列化が効果的 - Lambda環境でもスレッドプールは問題なく動作
7. 実装の詳細
コードの全体像を把握したい方向けのセクションです。
概要だけ知りたい方はコスト設計まで読み飛ばしてください。
7.1 メイン処理フロー
def handler(event, context):
station = event.get("station", "")
genre = event.get("genre", "")
force_refresh = event.get("forceRefresh", False)
cache_pk = f"RESULT#{station}#{genre}"
# キャッシュ確認(force_refresh時はスキップ)
if not force_refresh:
cached = get_cache(cache_pk)
if cached:
result = dict(cached)
result["costInfo"] = calc_cost(0, 0, 0, cached=True)
return result # コスト0円で即返却
# Google API(店舗検索と駅座標の並列取得)
with ThreadPoolExecutor(max_workers=2) as ex:
f_station = ex.submit(fetch_station_location, station)
f_places = ex.submit(fetch_google_places, station, genre)
station_loc = f_station.result()
places = f_places.result()
# ベイズ平均スコアリング
restaurants, score_detail = build_restaurants(places, genre)
# Bedrock並列処理(5並列)
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(enrich_item, item) for item in restaurants]
for f in as_completed(futures):
f.result()
# 写真キャッシュ確認 + 取得(20並列、S3/CloudFront経由)
fetch_all_photos_parallel(restaurants)
# キャッシュ保存 + 返却
save_cache(cache_pk, result)
return result
7.2 ベイズ平均の計算
def build_restaurants(places: list, genre: str) -> tuple[list, dict]:
ratings = [float(p["rating"]) for p in places if p.get("rating")]
prior_mean = statistics.mean(ratings) if ratings else 3.5
counts = [int(p.get("userRatingCount", 0)) for p in places
if p.get("userRatingCount", 0) > 0]
threshold = float(statistics.median(counts)) if counts else 50.0
for place in places:
rating = place.get("rating")
review_count = int(place.get("userRatingCount", 0))
score = (threshold * prior_mean + review_count * rating) / (threshold + review_count)
# ...
thresholdを検索結果全体の中央値から動的に算出することで、「渋谷の焼肉」と「地方の定食屋」のように母集団が異なるケースにも自動で適応します。
7.3 S3写真キャッシュ
def fetch_and_cache_photo(photo_name: str) -> str | None:
cloudfront_domain = get_cloudfront_domain()
if not S3_PHOTO_BUCKET or not cloudfront_domain:
return fetch_single_photo_url_legacy(photo_name)
# photo_nameのMD5ハッシュをS3キーとして使用
photo_hash = hashlib.md5(photo_name.encode()).hexdigest()
s3_key = f"photos/{photo_hash}.jpg"
# S3キャッシュ確認
try:
s3.head_object(Bucket=S3_PHOTO_BUCKET, Key=s3_key)
return f"https://{cloudfront_domain}/{s3_key}" # キャッシュHIT
except ClientError as e:
if e.response['Error']['Code'] != '404':
return fetch_single_photo_url_legacy(photo_name)
# キャッシュMISS: Google APIから取得 → S3に保存
photo_uri = fetch_photo_uri_from_google(photo_name)
image_data = download_image(photo_uri)
s3.put_object(
Bucket=S3_PHOTO_BUCKET, Key=s3_key,
Body=image_data, ContentType='image/jpeg',
CacheControl='public, max-age=604800'
)
return f"https://{cloudfront_domain}/{s3_key}"
MD5ハッシュキー
-
photo_nameは長い文字列のため、固定長ハッシュをS3キーに使用
フォールバック
- S3/CloudFront障害時はGoogle Places APIのURLを直接返却(サービス継続性を確保)
接続プール
-
max_pool_connections=25で20並列のHeadObject/PutObjectを効率的に処理
7.4 感情分析(Comprehend)
def analyze_sentiment_batch(reviews: list) -> dict:
target_reviews = reviews[:5]
texts = [r.get("text", "") for r in target_reviews if r.get("text")]
response = comprehend.batch_detect_sentiment(
TextList=texts, LanguageCode="ja"
)
reviews_by_sentiment = {"POSITIVE": [], "NEGATIVE": [], "NEUTRAL": [], "MIXED": []}
for i, result in enumerate(response.get("ResultList", [])):
sentiment = result.get("Sentiment", "NEUTRAL")
if i < len(texts):
reviews_by_sentiment[sentiment].append(texts[i])
return {
"sentiment": dominant_sentiment,
"scores": avg_scores,
"reviewCount": count,
"reviewsBySentiment": reviews_by_sentiment
}
フロントエンド側では、感情分析バーをクリックすると該当カテゴリのレビュー原文を表示する仕組みを実装しています。
![]() |
| 感情バーをクリック → 該当レビュー原文を表示 |
8. コスト設計:77円/検索から0円へ
8.1 S3キャッシュ導入前後の比較
| フェーズ | 1検索あたり | 写真コスト | 月100検索時 |
|---|---|---|---|
| 最適化前 | ¥99 | $0.56(87%) | ¥9,900 |
| S3キャッシュ導入後 (初回) |
¥77 | $0.42(60枚) | — |
| S3キャッシュ導入後 (2回目〜) |
¥12 | $0(CloudFront配信) | ¥1,200 |
| DynamoDBキャッシュHit | ¥0 | $0 | ¥0 |
8.2 現在の内訳(初回検索時)
| 項目 | 小計 | 割合 |
|---|---|---|
| Places API Photo Media(60枚) | $0.42 | 84% |
| Places API Text Search(2回) | $0.064 | 13% |
| Bedrock Claude Haiku(20店舗分) | $0.009 | 1.8% |
| Comprehend 感情分析(20店舗分) | $0.006 | 1.2% |
| 合計 | $0.50(≈77円) | 100% |
8.3 S3 + CloudFrontによる写真コスト最適化
写真取得はコストの84%を占める最大のボトルネックでした。そのため、以下の戦略で2回目以降のコストを低減しています。
初回
2回目~
| 項目 | 設計 |
|---|---|
| キャッシュキー | photo_nameのMD5ハッシュ(photos/{hash}.jpg) |
| ライフサイクル | 30日で自動削除(S3 Lifecycle Rule) |
| アクセス制御 | CloudFront OAI経由のみ公開 |
| フォールバック | S3障害時はGoogle Places APIのURLを直接返却 |
| 並列度 |
max_pool_connections=25で20並列アップロード |
月100検索(同一条件50%)の場合:
- Before: $56/月(写真のみ)
- After: $0.09/月(S3ストレージ + CloudFront転送量)
- 削減率: 99.8%
8.4 多層キャッシュ戦略
本システムでは3層のキャッシュでコストを段階的に削減しています。
| レイヤー | 対象 | TTL | 効果 |
|---|---|---|---|
| DynamoDB | 検索結果全体 | 1週間 | 2回目以降0円 |
| S3 + CloudFront | 写真データ | 30日 | 写真コスト99.8%削減 |
| CloudFrontエッジ | 配信済み写真 | 7日 | レイテンシ削減 |
検索結果(1週間)は飲食店のレビュー変動頻度に基づき、写真(30日)はストレージコストとAPI再取得コストのバランスで決定しています。
9. 使ってみる:川崎で焼肉を探す
実際の検索フローを紹介します。
9.1 Step 1: 条件設定
- 駅:川崎
- ジャンル:焼肉
- 絞り込み:2,000〜4,000円 / 10分以内 / 金曜日の19時に営業
![]() |
![]() |
| 駅選択 | ジャンル選択 |
![]() |
| 絞り込み条件 |
9.2 Step 2: 結果確認
ベイズ補正スコア順に表示されます。レビュー件数が少ない店舗は自動的に順位が下がります。
![]() |
| 絞り込み検索結果 |
9.3 Step 3: 詳細確認
ベイズスコア
- 4.51(Google評価: 4.6 / 1315件)
AI要約
- 「ビールケースの椅子が並ぶ雰囲気あるホルモン居酒屋で、新鮮なホルモンと遊び心のあるサービスが特徴。」
おすすめメニュー
- [馬肉とホルモンのミックスホルモンユッケ]
- [鉄板焼大トロホルモン塩]
- [バカ金ハイ]
感情分析
- ポジティブ 87% / ネガティブ 0% / 中立 13% / 混合 0%
9.4 Step 4: 予約
「マップ」もしくは「電話」ボタンから直接予約へ。
10. 振り返り:AWSサービス選定で学んだこと
今回の開発を通じて得た、AWSサービス選定に関する知見を共有します。
10.1 Bedrock vs SageMaker
当初はSageMakerでのモデルホスティングも検討しましたが、以下の理由からBedrockを選択しました。
| 観点 | Bedrock | SageMaker |
|---|---|---|
| 初期構築コスト |
ゼロ (APIコール課金のみ) |
エンドポイント構築が必要 |
| 運用負荷 | フルマネージド | モデル更新・スケーリングの 管理が必要 |
| レイテンシ | 十分高速 (1〜2秒/リクエスト) |
カスタムチューニングで 最適化可能 |
| ユースケース適合性 | 要約生成に最適 | 大規模推論・独自モデル向き |
個人開発〜中規模のAIアプリケーションであれば、Bedrockの「APIを叩くだけで推論できる」シンプルさは非常に大きな利点です。
10.2 Comprehend vs Bedrock(感情分析の使い分け)
感情分析をBedrockのプロンプトで行う選択肢もありましたが、以下の理由からComprehendを選択しました。
バッチ処理
-
batch_detect_sentimentで最大25テキストを1回のAPI呼び出しで処理可能
コスト効率
- プロンプトエンジニアリング不要
- ComprehendのバッチAPIの方がトークン課金より安い
出力の安定性
- 感情分析に特化した専用モデル
- LLMのように出力フォーマットが揺れない
適材適所の原則
- 生成が必要な処理(要約・メニュー抽出)はBedrock
- 分類が必要な処理(感情分析)はComprehend
全てをLLMに委ねるのではなく、タスクの性質に応じてサービスを使い分けることがコスト最適化の鍵です。
10.3 DynamoDB vs ElastiCache(キャッシュ層)
以下の理由からキャッシュにElastiCacheではなくDynamoDBを選択しました。
コスト
- ElastiCacheは最小構成(cache.t3.micro)でも月額約$15〜
- DynamoDBのオンデマンドモードなら月数円で済む
TTL
- DynamoDBのTTL機能で自動削除が可能
- Redisの
EXPIREと同等の機能をサーバーレスで実現
運用負荷
- VPC構成やクラスタ管理が不要
アクセス頻度が低く、レイテンシ要件もミリ秒単位を求めない用途では、DynamoDBで十分にキャッシュ層として機能します。
10.4 S3 + CloudFront vs 外部画像URL直接参照(写真配信)
以下の理由から写真をGoogle Places APIのURLそのまま返す方式から、S3キャッシュ + CloudFront配信に切り替えました。
| 観点 | 直接URL参照 | S3 + CloudFront(採用) |
|---|---|---|
| コスト | 毎回Places Photo API課金 ($0.007/枚) |
初回のみ課金 以降はS3ストレージ費のみ |
| レイテンシ | Google CDN依存 | CloudFrontエッジキャッシュで高速配信 |
| 可用性 | Google API障害に依存 | S3の99.99% SLAで安定配信 |
| URLの安定性 | セッション付きURL (有効期限あり) |
永続的なCloudFront URL |
設計上のポイントとして、S3バケットはCloudFront OAI(Origin Access Identity)のみを許可し、Lambda実行ロールには別途バケットポリシーでPutObject/GetObject権限を付与しています。この2層のアクセス制御により「Lambdaは書き込み可、ユーザーはCloudFront経由の読み取りのみ」を実現しています。
11. 今後の展望
| 機能 | 優先度 | 技術的課題 |
|---|---|---|
| エリア検索 (渋谷〜恵比寿の範囲指定) |
高 | ジオフェンシング実装 |
| レビュー数十件取得による 分析精度向上 |
中 | Place Details APIコスト(+$0.34/検索) |
| パーソナライズ推薦 | 中 | ユーザー行動履歴の蓄積設計 |
| 多言語対応 | 低 |
Comprehend多言語対応 フロントエンド国際化 |
12. まとめ
| 項目 | Before(Google Maps) | After(本アプリ) |
|---|---|---|
| ランキング精度 | 星4.5(3件)が上位に表示 | 星4.1(1,200件)が上位に表示 |
| 検索時間 | 約30分(手動調査) | 13秒 |
| 情報量 | 評価・件数のみ | +AI要約 +感情分析 +おすすめメニュー |
| コスト | 無料(ただし30分の時間コスト) | 77円(2回目以降12円、キャッシュHit時0円) |
本記事で実装・解説した技術要素:
- ベイズ平均によるレビュー件数バイアスの統計的補正
- Bedrock(Claude Haiku 4.5)による店舗情報の自動要約生成
- Comprehendによるレビュー感情分析(バッチ処理)
- S3 + CloudFrontによる写真キャッシュ(月間写真コスト99.8%削減)
-
ThreadPoolExecutorによる処理並列化(36秒→13秒、64%削減) - DynamoDB TTLキャッシュ + S3写真キャッシュの多層キャッシュ戦略
- CloudFormationによるインフラのコード化(IaC)
個人開発であっても、AWSのマネージドサービスを適切に組み合わせることで、運用負荷を抑えつつ実用的なAIアプリケーションを構築できることを示せたと考えています。
本記事が、AWSで生成AIを活用したアプリケーション開発に取り組む方の参考になれば幸いです。
この記事が役に立ったら、ぜひいいねやストックをしていただけると嬉しいです!
改めて、最後まで読んでいただき、ありがとうございました。
13. 参考文献
- Amazon Bedrock - 公式ドキュメント
- Amazon Comprehend - 自然言語処理
- Google Places API (New) - リファレンス
- AWS Lambda Python ランタイム
- DynamoDB TTL を使用して項目を期限切れにする
- Amazon S3 ライフサイクル管理
- Amazon CloudFront OAI
AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
その他、記載されている会社名および商品・製品・サービス名は、各社の商標または登録商標です。







