API キーは Internal Integration で
Public Integrationだと承認必須項目が大量。Internal Integrationなら設定が少なく、素早くセットアップできる。
ページ取得フロー
- ページ一覧取得
- 各ページのブロック子要素を再帰取得
- ブロックタイプごとにMarkdown変換
トラブルシューティング
query-data-source がエラー
データベースクエリは MCPの query-data-source より REST API 直接呼び出しが堅牢:
POST /v1/databases/{id}/query
テーブルブロック変換
テーブルブロックは table_row 子要素を取得して変換が必須。単独のテーブルブロック情報では行・セル情報が不足。
Notion 固有ブロック
- toggle:
details+summaryで実装 - callout:
blockquote+ emoji prefix で代替 - 内部リンク:
notion.so/xxxx→ VitePress 内リンクに変換
.mcp.json 配置
プロジェクトルートの .mcp.json は認識されるが、.claude/mcp.json は認識されない可能性あり。APIキーを含むため gitignore 必須。
アーキテクチャの進化
RAGはNaive → Advanced → Modular → Agenticへ進化中。2025年時点では以下が実装標準:
- Naive RAG: 単純な全文検索(過去)
- Advanced RAG: 再ランキング・クエリ展開など検索最適化
- Modular RAG: 検索・リランク・生成の各モジュール独立化
- Agentic RAG: LLMが「検索すべきか」を判断し動的に実行
ハイブリッド検索が実装標準
BM25(統計ベース)+ ベクトル検索の組み合わせが業界標準:
- BM25: キーワード完全一致に強く、計算コスト低い
- ベクトル: セマンティック類似性を捉える
- 結合手法: Reciprocal Rank Fusion (RRF) が堅牢で推奨
単一ベクトル検索より精度が安定し、本番環境で採用が加速している。
チャンク戦略の最新知見
| 項目 | 値 | 備考 |
|---|---|---|
| 最適サイズ | 256-512トークン | 言語モデル依存 |
| オーバーラップ | 10-20% | 文脈を繋ぐため必須 |
| コンテキスト上限 | ~2,500トークン | これ超過で品質cliff |
Contextual Retrieval(Anthropic提唱): チャンクにLLMで先行文脈説明を付加 → 検索エラー67%削減。コスト増だが精度向上は顕著。
Late Chunking: 文書全体を先に処理してからチャンク境界でプーリング。セマンティックチャンキングより実装簡単で、意外と精度が高い。
Markdownドキュメント向けベストプラクティス
- ヘッダーベース分割が最も自然で実用的
- セマンティックチャンキングは断片化リスク大・精度低い(54%)
- シンプルな固定サイズ + オーバーラップが堅牢
GraphRAG・Self-RAGの活用
- GraphRAG: エンティティ関係グラフでテーマ横断的な質問に対応。コスト50%削減報告あり
- Self-RAG: モデル自身が検索必要性を判断。不要な検索を削減
問題
wrangler r2 object put で R2 にファイルをアップロード → 確認したら何も入っていない。
原因
wrangler は デフォルトでローカル R2(miniflare)にアップロードする
実際の Cloudflare R2 に送るには --remote フラグが必須。
解決方法
# NG:ローカル R2 にのみアップロード
wrangler r2 object put my-bucket/document.md --file ./document.md
# OK:実際の Cloudflare R2 にアップロード
wrangler r2 object put my-bucket/document.md --file ./document.md --remote
確認方法
# ローカル R2 の内容確認(デフォルト)
wrangler r2 object list my-bucket
# リモート(実際)の R2 の内容確認
wrangler r2 object list my-bucket --remote
ベストプラクティス
自動同期スクリプト(GitHub Actions等)では 必ず --remote を指定 する。
# GitHub Actions での R2 アップロード例
- name: Upload to R2
run: |
wrangler r2 object put leango-docs/docs.md \
--file ./dist/docs.md \
--remote
デバッグ Tips
アップロード後の検証:
# リモート確認
wrangler r2 object list my-bucket --remote
# ダウンロード確認
wrangler r2 object get my-bucket/document.md --remote
デフォルトで悩むのは一度で終わらせよう。
問題
GCP の App Engine を停止(disable)すると、それに紐づくデフォルト Firestore データベース (default) も一緒に無効化される。これは GCP の仕様。
原因
デフォルト Firestore データベースは歴史的に App Engine と紐づけられている設計のため、App Engine のライフサイクルと連動している。
対処法
Firestore を生かしたままにしたい場合:
- App Engine を再有効化する必要がある
- トラフィックを止めたいだけなら、DNS を別のサービスに向けて App Engine にアクセスが来ないようにする(停止ではなく放置)
重要: トラフィック遮断と リソース無効化を混同しないこと。DNS 切り替えで十分な場合がほとんど。
SSG + 少数SSRの構成でのリソース設計
静的ページはCDNから配信されるため、Cloud Runに到達するのはSSRエンドポイント(プレビュー・API・フォーム送信)のみ。初期構成は以下で十分:
- CPU: 1 / メモリ: 512MiB
- minInstances: 0 / maxInstances: 10
- 実使用量:約120MB(使用率24%)
minInstances: 0 のトレードオフ
コールドスタートで数秒の起動遅延が発生するが、影響はSSRのみ。フォーム送信での数秒遅延は許容範囲。minInstances: 1にすると月$5〜10のコスト常時発生。
スケールアップが必要なサイン
| 指標 | 危険ライン | 対応 |
|---|---|---|
| CPU | 常時70%超 | cpu: 1 → 2 |
| メモリ | 常時80%超 | 512 → 1024 MiB |
| SSRレスポンス | 5秒超 | CPU or メモリ増加 |
| 5xx エラー | OOM クラッシュ | メモリ増加が急務 |
スケール戦略の優先順位
- 水平スケール:maxInstances を増加(最初に試す)
- 垂直スケール:1インスタンスの処理能力が足りない時だけCPU/メモリを上げる
トラフィック増への強度
静的ページへのアクセス50倍増でもCloud Runへの負荷はほぼ変わらず。1インスタンス × 同時80リクエスト × 最大10インスタンス = 同時800リクエスト処理可能。
計画フェーズ: TTL事前短縮
TTL(Time To Live)とは
DNSレコードが世界中のDNSサーバーにキャッシュされる秒数。
- TTL 3600秒: 1時間キャッシュ保持
- TTL 300秒: 5分キャッシュ保持
なぜ事前に下げるか
問題発生時のロールバック速度を確保するため。
旧TTL(3600秒)のままIP切替すると、問題発生→即戻しでもキャッシュ有効期間中はユーザーが新サーバーにアクセスし続ける。最大1時間のエラー継続リスク。
ベストプラクティス
- DNS切替の24〜48時間前にTTLを300秒に短縮
- 切替後、安定稼働を確認したら元のTTL値(3600以上)に戻す
TTL短縮を忘れた場合
- 最も安全: TTLを300に変更→1時間待機(旧キャッシュ完全消滅)→作業開始
- 妥協案: TTLを300に変更→すぐ作業開始(大半は5分で浸透、一部残留リスク)
- リスク高: TTL 3600のまま作業開始(ロールバック時に最大1時間の影響)
実行フェーズ: DNS切替
DNSレコードを新サーバーのIPアドレスに変更する。浸透には最大48時間かかるため、初期段階でのトラフィック不足は正常。
監視フェーズ: 切替後のダッシュボード確認
正常な状態
- 5xx: 0 / 4xx: 少数(正常範囲) / CPU: 低い(2%程度) / メモリ: 低い(24%程度) / 2xx: トラフィックに応じて増加
問題ありの兆候
| 指標 | 状態 | 対応 |
|---|---|---|
| 5xx ≥ 1 | SSR/APIに問題 | ログ確認、深刻ならロールバック |
| 4xx 急増 | ルーティング/リダイレクト設定ミス | 旧パスの404を調査 |
| CPU > 50% | SSR過負荷 | ページ最適化/スケール調整 |
| メモリ > 80% | メモリリーク等 | プロセス調査 |
| 2xx = 0 | DNS未浸透 or SSL未発行 | dig domain.com A で確認 |
監視フロー
- 切替後30分〜1時間: 継続的にダッシュボード監視
- 最初1〜2日間: TTLを300秒のまま維持(即ロールバック可能に)
- 安定確認後: TTLを3600に戻す
課題
チームでgit管理している設定ファイル(エディタ設定、AI設定など)を頻繁にローカル修正するが、毎回 git status に差分が出て邪魔。かといってgit管理から完全に外すと、チームへの共有ができなくなる。
解決: --skip-worktree
# 適用(ローカル変更をgitに無視させる)
git ls-files <dir>/ | xargs git update-index --skip-worktree
# 解除(再びgitで変更を追跡する)
git ls-files <dir>/ | xargs git update-index --no-skip-worktree
--assume-unchanged との違い
| フラグ | 用途 | git resetで解除 |
|---|---|---|
--assume-unchanged | パフォーマンス最適化 | される |
--skip-worktree | 意図的なローカル変更の無視 | されない |
ローカル設定のカスタマイズには --skip-worktree が適切。
注意点
- ローカル専用の設定。チームメンバーも各自で実行が必要
- リモートで対象ファイルが更新されると
git pull時にコンフリクトする可能性あり(一時的に解除して対応) - 新規追加ファイル(未追跡)は対象外。必要なら
.gitignoreで対応
問題
Cloudflare Pagesプロジェクトに wrangler.json(または .jsonc)が存在すると、ビルド時にダッシュボードで設定した環境変数が読み込まれない。
ビルドログに以下が出る:
Checking for configuration in a Wrangler configuration file (BETA)
Found wrangler.json file. Reading build configuration...
Build environment variables: (none found)
原因
wrangler.json ベースの設定(BETA)が有効になると、ダッシュボードのビルド設定を完全に上書きする。wrangler.json に環境変数の定義がなければ「none found」になる。
ダッシュボードの「変数とシークレット」セクションで設定した値はランタイム用バインディングとして扱われ、ビルドプロセスには渡されない。
対処法
wrangler.jsonを削除/リネームしてダッシュボード設定に戻す(シークレットをgitに入れずに済む)pages_build_output_dir等はダッシュボードの「ビルド出力」で設定可能- ローカルの
astro devやwrangler pages dev(引数指定)には影響なし
料金の核心
静的アセットへのリクエストは完全無料・無制限。課金対象はPages Functions(サーバーレス)のみ。
Freeプラン($0/月)
| 項目 | 制限 |
|---|---|
| 静的リクエスト | 無制限 |
| 帯域幅 | 無制限 |
| サイト数 | 無制限 |
| ビルド | 500回/月 |
| 同時ビルド | 1 |
| Functions | 100,000リクエスト/日(Workers共有) |
Paidプラン($5/月〜)
ビルド5,000回/月、同時ビルド20、Functions 1,000万リクエスト/月含む。
判断基準
output: 'static'の静的サイト → Freeで十分- SSR/Functions使う場合 → Paidプランの$5/月〜
- ビルド頻度が月500回超えるCI/CD → Paid検討
NetlifyやVercelと比べて帯域幅無制限が大きな差別化ポイント。
背景
フルスタック Web 開発では「どのバックエンド使うか」という選択肢が多い。
- Firebase Cloud Functions
- AWS Lambda
- Google Cloud Functions
- Cloudflare Workers
- Vercel Functions
- 自社 VM / Kubernetes
アンチパターン
単なる Slack webhook POST → Firebase Cloud Functions + GCP VM
課題
- 過剰エンジニアリング: インフラの複雑さが実装の 10 倍
- 学習曲線: Firebase SDK の理解 / GCP コンソール操作
- 運用コスト: 監視、ログ、スケーリング設定
- 冗長性: 単純な処理に高可用性インフラは不要
原則:逆算発想
1. 必要な処理は何か?
→ Slack Webhook 1 行の POST
2. どのくらいのスケールか?
→ コーポレートサイト、月 100 件程度の問い合わせ
3. どのインフラがそれに適切か?
→ API Gateway / Edge Function で十分
❌ Firebase(学習コスト高い)
❌ Cloud Run(常時起動 VM)
✓ CF Pages Functions(エッジで即実行、無制限)
判断表
| 必要な処理 | 推奨インフラ | 理由 |
|---|---|---|
| Webhook POST / メール送信 | CF Functions / Vercel API | 単発実行、低レイテンシ |
| CRUD API + DB | Supabase / Firebase Realtime | リアルタイム必須 |
| バッチ処理 / 長時間実行 | Cloud Tasks / Temporal | スケジュール・リトライ |
| リアルタイム双方向通信 | WebSocket (Vercel KV / Durable Objects) | ステートフル |
| 機械学習推論 | Lambda / Cloud Functions | 計算量多い |
移行ケース
Before(過剰)
Next.js (GCP App Engine)
↓
Firebase Cloud Functions
↓
Slack Webhook
- 起動:
gcloud app deploy(数分待ち) - 監視: GCP コンソール + Firebase console
- コスト: 月 $10-50(Free tier外)
After(最小化)
Astro static (CF Pages)
↓
CF Pages Functions(同一プロジェクト)
↓
Slack Webhook
- デプロイ:
wrangler deploy(秒単位) - 監視: CF dashboard 一箇所
- コスト: 月 $0(Free 10万req/日)
チェックリスト:この技術は必要か?
- 実装なしに同じ結果を得られないか?(No = 必要)
- 学習コストは実装メリットに見合うか?
- 運用オーバーヘッド(監視、スケーリング、ログ)は将来的に必要か?
- チーム全体が使いこなせるスキルセットがあるか?
- 本番環境での障害時の対応ができるか?
1 つでも No なら、もっと単純な選択肢を検討する。
学び
「機能しているから」という理由で複雑性を受け入れない。 移行時が技術選定を見直すベストタイミング。