<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Edge on Tarragon</title><link>https://tarrragon.github.io/blog/tags/edge/</link><description>Recent content in Edge on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 21 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/edge/index.xml" rel="self" type="application/rss+xml"/><item><title>Cloudflare WAF</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/</guid><description>&lt;p>Cloudflare WAF 是 &lt;em>edge-deployed&lt;/em> 的 Web Application Firewall、跑在 Cloudflare 全球 anycast 網路上、攔截 HTTP/HTTPS 攻擊在抵達 origin 之前。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a> 的核心差異是 &lt;em>跟其他 Cloudflare 產品深度整合&lt;/em>：DDoS protection、Bot Management、Rate Limiting、Page Shield（JS supply chain）、API Shield（schema validation）、Zero Trust、Workers 邊緣計算共用同一個控制面。客戶選 Cloudflare WAF 通常不只是要 WAF、是要 &lt;em>整套 edge security suite&lt;/em>。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Cloudflare WAF 的核心定位是 &lt;em>把攻擊擋在 origin 之前的一站式 edge security&lt;/em>。流量打到 Cloudflare anycast IP、經過 WAF / DDoS / Bot / Rate Limit / Page Shield 多層處理、再 proxy 到 origin。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 跑在 AWS 內部 ALB / CloudFront / API Gateway 前是不同部署模型 — AWS WAF 流量 &lt;em>已經進到 AWS&lt;/em>、Cloudflare WAF 流量 &lt;em>還沒到 origin&lt;/em>。對 origin 是 &lt;em>任意雲 / on-prem&lt;/em> 的客戶、Cloudflare 是天然選項；對 AWS-only 客戶、AWS WAF 整合更深但 edge 範圍小。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &amp;#43; ATO &amp;#43; Bot 一體">Fastly Next-Gen WAF&lt;/a>（前 Signal Sciences）相比、Cloudflare 走 &lt;em>signature + managed rule + ML&lt;/em> 混合、Fastly NG-WAF 走 &lt;em>語意分析 + behavioral detection&lt;/em>（不靠 regex signature）。Cloudflare managed rule 覆蓋廣但 false positive 較常見、需要 &lt;em>sensitivity tuning&lt;/em>；Fastly NG-WAF 預設較低 FP 但需要 &lt;em>自己定義業務 anomaly&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<p>Cloudflare WAF 是 <em>edge-deployed</em> 的 Web Application Firewall、跑在 Cloudflare 全球 anycast 網路上、攔截 HTTP/HTTPS 攻擊在抵達 origin 之前。它跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a> 的核心差異是 <em>跟其他 Cloudflare 產品深度整合</em>：DDoS protection、Bot Management、Rate Limiting、Page Shield（JS supply chain）、API Shield（schema validation）、Zero Trust、Workers 邊緣計算共用同一個控制面。客戶選 Cloudflare WAF 通常不只是要 WAF、是要 <em>整套 edge security suite</em>。</p>
<h2 id="服務定位">服務定位</h2>
<p>Cloudflare WAF 的核心定位是 <em>把攻擊擋在 origin 之前的一站式 edge security</em>。流量打到 Cloudflare anycast IP、經過 WAF / DDoS / Bot / Rate Limit / Page Shield 多層處理、再 proxy 到 origin。這跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 跑在 AWS 內部 ALB / CloudFront / API Gateway 前是不同部署模型 — AWS WAF 流量 <em>已經進到 AWS</em>、Cloudflare WAF 流量 <em>還沒到 origin</em>。對 origin 是 <em>任意雲 / on-prem</em> 的客戶、Cloudflare 是天然選項；對 AWS-only 客戶、AWS WAF 整合更深但 edge 範圍小。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a>（前 Signal Sciences）相比、Cloudflare 走 <em>signature + managed rule + ML</em> 混合、Fastly NG-WAF 走 <em>語意分析 + behavioral detection</em>（不靠 regex signature）。Cloudflare managed rule 覆蓋廣但 false positive 較常見、需要 <em>sensitivity tuning</em>；Fastly NG-WAF 預設較低 FP 但需要 <em>自己定義業務 anomaly</em>。</p>
<p>關鍵張力：客戶信任的不只是 <em>WAF rule 攔截能力</em>、還包括 <em>Cloudflare control plane 的安全性</em>。<a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare 2023 control plane token</a> 跟 <a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">Cloudflare 2026 route leak</a> 兩個事件展示：vendor 自己被打進去 / 自動化配置失誤時、客戶側 <em>直接修不了</em>、只能等公告 + 客戶側 token rotation + emergency bypass。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Cloudflare WAF 在 edge security stack 中承擔哪一段（DDoS / WAF / Bot / Page Shield / API Shield）、哪些要靠 origin 自己做</li>
<li>Managed Rule vs Custom Rule 的取捨、sensitivity tuning 跟 false positive curve</li>
<li>Cloudflare control plane 出事時的客戶側補強路徑（API token rotation、Origin Rules bypass、第二邊界 fallback）</li>
<li>何時用 Cloudflare、何時走 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly NG-WAF</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Cloudflare WAF 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>誰能改 WAF 規則</strong>：Cloudflare account 的 admin / member role 配置、API token scope（不要用 Global API Key、用 scoped API token + 限定 zone / 限定 permission）、Audit Log 是否同步到 SIEM</li>
<li><strong>規則覆蓋面</strong>：Managed Ruleset（OWASP Core Ruleset + Cloudflare Managed Ruleset + Exposed Credentials Check）是否開、Sensitivity（Low / Medium / High）對應的 FP rate 是否監控、Custom Rule 是否進版控（Terraform provider）</li>
<li><strong>入口暴露</strong>：origin IP 是否曝光（DNS 直查 / 歷史 SAN cert / 子域名）、Argo Tunnel / Authenticated Origin Pull 是否強制、繞過 Cloudflare 直連 origin 的路徑是否封住</li>
<li><strong>證據可回查</strong>：Security Events Log 是否同步到 SIEM（Logpush 推到 R2 / S3 / Splunk）、Page Shield 偵測異常 script 是否 alert、API token 異常操作（特別 zone settings 變更）是否 alert</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">Entry Point Protection</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>Managed Ruleset 分層</strong>：Cloudflare 提供三類 managed rule — <em>OWASP Core Ruleset</em>（OWASP CRS、寬覆蓋、FP 較多）、<em>Cloudflare Managed Ruleset</em>（Cloudflare 維護、針對熱門 CMS / framework）、<em>Exposed Credentials Check</em>（檢測登入流量中的已洩漏 credential）。production 通常開全部三套 + 各設適當 sensitivity。Sensitivity 不是「敏感度越高越好」— High sensitivity 攔截更多 borderline traffic、business-critical endpoint 可能誤殺合法請求。建議從 <em>Log Mode</em> 開始、觀察 1-2 週的 FP pattern、再切到 <em>Block</em>。</p>
<p><strong>Custom Rule（Cloudflare Rules）</strong>：用 Rules language（類 SQL 表達式）定義條件 + 動作（Block / Challenge / Log / JS Challenge / Managed Challenge）。常見用法：geo block（特定國家）、known bad IP（threat intel feed）、URI path-based limit（admin endpoint 限定 IP）、header anomaly（缺 User-Agent / 異常 Referer）。所有 Custom Rule 走 Terraform provider 進版控、避免 console 直接改、變更走 PR review。</p>
<p><strong>Rate Limiting</strong>：跟 WAF rule 是 <em>獨立 product</em>、配置是 <em>threshold + window + action</em>（例：1000 req/min per IP → challenge）。Rate Limiting 比 WAF 適合處理 <em>legitimate-looking high volume</em>（credential stuffing、scraping、API abuse）。注意 <em>NAT pool IP</em> 的問題 — 一個公司 / ISP NAT 出口可能合法產生高 QPS、簡單 per-IP rate limit 會誤殺、需要組合 <em>cf.threat_score</em> 或 <em>cookie-based identification</em>。</p>
<p><strong>Bot Management（單獨 SKU）</strong>：免費版 WAF 不含 Bot Management、需要 Pro / Business / Enterprise 才有。Bot Management 用 ML + behavioral fingerprint 區分 <em>human / good bot（搜尋引擎）/ likely bot / verified bot</em>、給 bot score（1-99）。客戶在 Custom Rule 用 <code>cf.bot_management.score &lt; 30</code> 之類條件挑出 likely bot 處理。簡單 user-agent 過濾擋不住現代 headless browser、必須走 Bot Management。</p>
<p><strong>Page Shield（JS supply chain 防護）</strong>：Page Shield 監測客戶網頁載入的 JS / connect 來源、發現 <em>新出現的腳本</em> 或 <em>已洩漏的 script</em>（CT log + threat intel）就 alert。意義是 <em>防 third-party script 被供應鏈攻擊</em>（類 <a href="https://en.wikipedia.org/wiki/Magecart">Magecart</a>）— WAF 攔不住、因為攻擊發生在 <em>browser 端</em> 而非 <em>origin 流量</em>。需要在 Page 載入 Page Shield 的 monitoring script。</p>
<p><strong>API Shield</strong>：用 OpenAPI schema validation、auto-discovery API endpoint、mTLS 驗證、JWT validation。對於有 schema 的 API、可以擋掉 <em>schema 不符的請求</em>（多餘欄位、型別錯誤、缺必要欄位）— 比 generic WAF rule 精準。</p>
<p><strong>Origin 暴露面收緊</strong>：Cloudflare 唯一有效的前提是 <em>流量必須經過 Cloudflare</em>。如果攻擊者拿到 origin 真實 IP（DNS 歷史記錄、漏洞披露網站、SSL cert SAN）、可以繞過 Cloudflare 直打 origin。控制方法：origin firewall 只允許 Cloudflare IP range 入站、Argo Tunnel（origin 主動建 outbound 連線到 Cloudflare、不開任何入站 port）、Authenticated Origin Pull（origin 用 cert 驗證請求來自 Cloudflare）三選一或組合。</p>
<p><strong>API token 治理</strong>：避免 Global API Key（全帳號 root token）、改用 <em>scoped API token</em>（限 zone + 限 permission + 限 IP + 限 TTL）。token 進 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> / <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、定期 rotate。對應 <a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare control plane token 2023</a> 揭示的 lesson：Cloudflare 自己也踩過 token 治理不足、客戶側不能假設 vendor 完美。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Cloudflare WAF</th>
          <th>AWS WAF</th>
          <th>Fastly Next-Gen WAF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>部署位置</td>
          <td>Cloudflare global edge（300+ POP）</td>
          <td>AWS region 內 ALB / CloudFront / API Gateway 前</td>
          <td>Fastly edge + Agent + Module（自管 Nginx / Apache / Envoy / IIS）+ Cloud WAF proxy、三模型可混</td>
      </tr>
      <tr>
          <td>Origin 中立性</td>
          <td>強 — origin 可以是任何雲 / on-prem</td>
          <td>弱 — 跟 AWS 緊耦合（限 AWS service 前）</td>
          <td>強 — Fastly CDN / 任何 origin</td>
      </tr>
      <tr>
          <td>偵測模型</td>
          <td>Signature + Managed Rule + ML</td>
          <td>Signature + Managed Rule + Lambda 自訂</td>
          <td>Signal / behavioral（語意分析、低 FP）</td>
      </tr>
      <tr>
          <td>DDoS 內建</td>
          <td>是 — 跟 WAF 同套餐</td>
          <td>AWS Shield Standard 內建、Advanced 加價</td>
          <td>內建 + Fastly DDoS</td>
      </tr>
      <tr>
          <td>Bot Management</td>
          <td>加價 add-on（Pro / Business / Enterprise）</td>
          <td>AWS WAF Bot Control</td>
          <td>加價 add-on</td>
      </tr>
      <tr>
          <td>JS supply chain</td>
          <td>Page Shield（Business+）</td>
          <td>無原生、靠後端 CSP / 第三方</td>
          <td>Inline JS monitoring（Next-Gen WAF 部分）</td>
      </tr>
      <tr>
          <td>API schema</td>
          <td>API Shield（Enterprise）</td>
          <td>AWS WAF + API Gateway request validator</td>
          <td>NG-WAF inline + sigsci-agent</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — UI / Rules language 易上手、Terraform 完整</td>
          <td>較陡 — JSON policy + 跟 AWS service 整合多軌</td>
          <td>中 — agent 安裝 + Signal 語意設定</td>
      </tr>
      <tr>
          <td>第三方信任成本</td>
          <td>高 — Cloudflare 控制面（2023、2026 自家事件）</td>
          <td>中 — AWS 控制面、跟 IAM 同套</td>
          <td>中 — Fastly 控制面（規模小、事件少但社群影響也小）</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>Multi-cloud / on-prem origin、要整套 edge security</td>
          <td>AWS-heavy、ALB / CloudFront 是主要入口</td>
          <td>高 FP 容忍度低、業務有 schema、想避 regex signature</td>
      </tr>
  </tbody>
</table>
<p>選 Cloudflare WAF 的核心訴求：<em>多雲 / on-prem origin</em> + 需要 <em>整套 edge security suite</em>（DDoS + WAF + Bot + Page Shield + API Shield） + 接受 Cloudflare 控制面風險、且有預算做 Enterprise tier 才能拿到完整功能。純 AWS-internal app + ALB origin 用 AWS WAF 整合更直接。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>Workers + Workers AI 作為 custom logic</strong>：當 managed rule + custom rule 表達力不夠（例：根據 user account tier 決定 challenge 強度、整合內部 risk score API）、可以用 Cloudflare Workers 寫 JavaScript / TypeScript / Rust 在 edge 執行。Workers AI 提供 edge ML inference、可以做 inline content moderation 或 anomaly detection。代價是 <em>Workers code 進 Cloudflare 控制面</em>、變更要走部署流程、debug 跟 origin 是兩條 trace。</p>
<p><strong>Logpush 跟 SIEM 整合</strong>：Cloudflare Security Events 量大、free / Pro 在 dashboard 看、Business / Enterprise 走 Logpush 到 R2 / S3 / Splunk / Datadog / Sumo Logic。production 必須走 Logpush、不能只在 dashboard — 事件 30 天保留期是 Cloudflare 端、SIEM 留更久。Logpush 也是 SIEM 上做 <em>跨來源 correlation</em> 的前提（WAF event + origin app log + IdP log）。</p>
<p><strong>Multi-account / Tenant</strong>：大企業有多個 Cloudflare account（不同 BU / 不同產品線）、要走 <em>Cloudflare for SaaS</em> 或 <em>Account-level access</em>、API token scope 要限定 account。Single account 多 zone 是常見小組織配置、但跨組織 / 跨產品線必須拆 account 隔離 admin compromise blast radius。</p>
<p><strong>Magic Transit / Zero Trust integration</strong>：Magic Transit 是 L3 DDoS（不只 HTTP、TCP / UDP 也 anycast）、Zero Trust 是 employee access（取代 VPN）。跟 WAF 是不同產品、但常一起部署 — Magic Transit 防 L3/L4 attack、WAF 防 L7、Zero Trust 防內部 east-west。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Managed Rule 誤殺合法請求</strong>：High sensitivity 開後 business endpoint 變慢 / 報錯 — 看 Security Events 找 rule_id、用 Custom Rule skip 該 rule 在特定 path / 特定 user-agent、不要全 zone 關 rule</li>
<li><strong>Bot Management 太嚴 / 太鬆</strong>：bot score threshold 設不對、合法 API client 被當 bot、或攻擊者拿到 verified bot 假冒 — 用 <em>Bot Analytics</em> 看分數分布、調整 threshold 同時加白名單（API key + IP CIDR）</li>
<li><strong>Rate Limit 誤殺 NAT 用戶</strong>：per-IP rate limit 在 NAT 出口 IP 上炸 — 改 per-session（cookie-based）或 cf.threat_score 條件</li>
<li><strong>Origin IP 外洩</strong>：DNS 歷史 + 漏洞披露 + cert SAN 揭露真實 origin、攻擊繞 Cloudflare 直打 — 換 IP + 開 origin firewall（只允許 Cloudflare CIDR）+ Argo Tunnel</li>
<li><strong>API token over-scoped</strong>：CI / 第三方 SaaS 拿到 Global API Key、整 account 都被改 — 改 scoped token、限 zone + permission + IP、進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a></li>
<li><strong>Security Events 沒進 SIEM</strong>：事件只在 dashboard、跨來源 correlation 沒法做 — 配 Logpush + alert 規則</li>
<li><strong>Page Shield 沒裝</strong>：客戶端 JS 被植入、伺服器端日誌看不到攻擊、第三方 script CDN 被打 — 啟用 Page Shield + CSP report-uri 雙軌</li>
<li><strong>第二邊界沒設</strong>：完全依賴 Cloudflare、Cloudflare 出事流量全停（<a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">2023 / 2026 自家事件</a>）— 高 SLA 服務應該設 fallback origin / secondary DNS（如 Route53 health check failover 到 Fastly 或直連 origin）</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + ALB / CloudFront origin</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>低 FP 容忍 / 業務有 schema</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></td>
      </tr>
      <tr>
          <td>純內部 mTLS / east-west</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + service mesh</td>
      </tr>
      <tr>
          <td>Cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>客戶端 JS supply chain</td>
          <td>Page Shield + <a href="/blog/backend/07-security-data-protection/supply-chain-integrity-and-artifact-trust/" data-link-title="7.12 供應鏈完整性與 Artifact 信任" data-link-desc="定義 build provenance、artifact 信任與交付鏈風險問題">supply chain integrity</a></td>
      </tr>
      <tr>
          <td>DDoS L3/L4</td>
          <td>Cloudflare Magic Transit / AWS Shield Advanced</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Cloudflare 完整 product line（Workers / Pages / R2 / D1 / Magic Transit / Zero Trust 各自細節）</li>
<li>WAF Rules language 完整語法 reference</li>
<li>Page Shield / API Shield Enterprise tier 完整功能對照</li>
<li>各 PCI DSS / SOC 2 / FedRAMP 合規矩陣</li>
<li>Cloudflare 在中國的部署模式（JD Cloud Union 合作）</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Cloudflare WAF 在 07 案例庫有 <em>兩個直接 vendor-level 事件</em> + 多個 edge-exposure 對照：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Cloudflare WAF 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/cloudflare-control-plane-token-2023/" data-link-title="7.C2 Cloudflare：2023 Control-plane Token 事件" data-link-desc="控制面 token 事件如何回寫 secrets 與機器憑證治理。">Cloudflare Control Plane Token 2023</a></td>
          <td>直接 — Cloudflare 自家 API token 治理不足、客戶側必須假設 vendor 也會被打、API token rotation 跟 IP allowlist 必做</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/cases/cloudflare-route-leak-2026/" data-link-title="7.C1 Cloudflare：2026 Route Leak 事件" data-link-desc="BGP 路由政策自動化失誤如何回寫控制面治理。">Cloudflare Route Leak 2026</a></td>
          <td>直接 — 自動化路由配置錯誤導致流量擁塞、客戶側應有 secondary DNS / failover origin 預案</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — WAF 攔不住 edge appliance zero-day、需要「修補 + session 失效 + 異常清查」三同步</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/fortinet-cve-2023-27997-sslvpn-overflow/" data-link-title="7.R7.3.21 Fortinet 2023：CVE-2023-27997 SSL-VPN 溢位" data-link-desc="SSL-VPN 漏洞在邊界設備上會放大大規模掃描與利用速度">Fortinet SSL-VPN CVE 2023-27997</a></td>
          <td>對照啟示 — vendor patch 前的臨時 WAF rule + 收斂可達來源是修補窗口期的標準動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — WAF rule 是 emergency mitigation、但 exploitation 過 WAF 後在後端執行、不能單靠 WAF 防後端 supply chain</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/identity-access/okta-cloudflare-2023-support-supply-chain/" data-link-title="7.R7.1.2 Okta &#43; Cloudflare 2023：支援流程與身分供應鏈" data-link-desc="支援工單與第三方身份供應商路徑如何變成入侵鏈的一部分">Okta-Cloudflare 2023 Support Supply Chain</a></td>
          <td>對照啟示 — 上游 IdP 出事傳導到 Cloudflare admin 帳號、API token / admin session 要立即 rotate、不等供應商公告</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/" data-link-title="Fastly Next-Gen WAF" data-link-desc="Behavioral / 語意分析 WAF（前 Signal Sciences）、低 false positive、Edge / Agent / Cloud 三種部署模型、API &#43; ATO &#43; Bot 一體">Fastly Next-Gen WAF</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（WAF block 不夠時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（Cloudflare API token 存放）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（Cloudflare admin 走 SSO）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（WAF block 事件 / Cloudflare 自家事件如何 routing 進 IR）</li>
<li>官方：<a href="https://developers.cloudflare.com/waf/">Cloudflare WAF Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>Fastly Next-Gen WAF</title><link>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/fastly-ngwaf/</guid><description>&lt;p>Fastly Next-Gen WAF（NG-WAF）的核心定位是 &lt;em>用語意分析 + behavioral detection 取代 regex signature&lt;/em> 的 web application firewall。它前身是 2020 年被 Fastly 收購的 Signal Sciences、跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 的根本差異不在覆蓋面、在 &lt;em>偵測 mindset&lt;/em> — 不靠 pattern 比對、靠解析請求語意（這段內容像不像 SQL、像不像 shell command）跟跨請求行為模式（同一 token 在多 endpoint 連續觸發異常）下判斷。產出是 &lt;em>低 false positive 的 inline block 模式可以直接上 production&lt;/em>、不需要先養 Log Mode 兩週、不需要 SOC 全職人員跟 rule 戰。&lt;/p>
&lt;h2 id="服務定位">服務定位&lt;/h2>
&lt;p>Fastly NG-WAF 設計的第一順位是 &lt;em>production 可直接走 Block 模式&lt;/em>。Signature WAF 的成本不在 rule 本身、在 false positive — 一條 SQLi pattern 可能誤判合法 SQL-like 字串（搜尋查詢、CSV 上傳）、production 開 Block 立刻炸合法流量、所以多數 signature WAF 跑在 &lt;em>Detect / Log Only&lt;/em> 模式、攔不下真正攻擊。Fastly NG-WAF 走 &lt;em>Signal&lt;/em> 模型：每個請求被解析後標記若干 Signal（SQLi、XSS、CMDI、Traversal、Anomaly 等）、再依 &lt;em>threshold-based rule&lt;/em>（N 個 Signal 在 M 秒內聚集）才動作 — false positive 自然降低、Block 模式可開。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &amp;#43; DDoS &amp;#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF&lt;/a> 的對照：Cloudflare 走 signature + managed rule + ML 三層、覆蓋廣但需要 sensitivity tuning；Fastly NG-WAF 預設低 FP 但需要 &lt;em>客戶自己定義業務語意&lt;/em>（哪些 path 是 admin、哪些 header 不該出現、哪些 anomaly 對自家業務代表攻擊）— 用 &lt;em>Tag&lt;/em> + &lt;em>Match Conditions&lt;/em> 表達。跟 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &amp;#43; Managed Rule Group &amp;#43; Rate-based Rule、Shield Standard 內含">AWS WAF&lt;/a> 的對照：AWS WAF 跟 ALB / CloudFront / API Gateway 整合深、跨雲弱；Fastly NG-WAF 部署模型多樣（Edge / Agent / Cloud）、跨 AWS / GCP / on-prem / K8s 一致。&lt;/p></description><content:encoded><![CDATA[<p>Fastly Next-Gen WAF（NG-WAF）的核心定位是 <em>用語意分析 + behavioral detection 取代 regex signature</em> 的 web application firewall。它前身是 2020 年被 Fastly 收購的 Signal Sciences、跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的根本差異不在覆蓋面、在 <em>偵測 mindset</em> — 不靠 pattern 比對、靠解析請求語意（這段內容像不像 SQL、像不像 shell command）跟跨請求行為模式（同一 token 在多 endpoint 連續觸發異常）下判斷。產出是 <em>低 false positive 的 inline block 模式可以直接上 production</em>、不需要先養 Log Mode 兩週、不需要 SOC 全職人員跟 rule 戰。</p>
<h2 id="服務定位">服務定位</h2>
<p>Fastly NG-WAF 設計的第一順位是 <em>production 可直接走 Block 模式</em>。Signature WAF 的成本不在 rule 本身、在 false positive — 一條 SQLi pattern 可能誤判合法 SQL-like 字串（搜尋查詢、CSV 上傳）、production 開 Block 立刻炸合法流量、所以多數 signature WAF 跑在 <em>Detect / Log Only</em> 模式、攔不下真正攻擊。Fastly NG-WAF 走 <em>Signal</em> 模型：每個請求被解析後標記若干 Signal（SQLi、XSS、CMDI、Traversal、Anomaly 等）、再依 <em>threshold-based rule</em>（N 個 Signal 在 M 秒內聚集）才動作 — false positive 自然降低、Block 模式可開。</p>
<p>跟 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> 的對照：Cloudflare 走 signature + managed rule + ML 三層、覆蓋廣但需要 sensitivity tuning；Fastly NG-WAF 預設低 FP 但需要 <em>客戶自己定義業務語意</em>（哪些 path 是 admin、哪些 header 不該出現、哪些 anomaly 對自家業務代表攻擊）— 用 <em>Tag</em> + <em>Match Conditions</em> 表達。跟 <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的對照：AWS WAF 跟 ALB / CloudFront / API Gateway 整合深、跨雲弱；Fastly NG-WAF 部署模型多樣（Edge / Agent / Cloud）、跨 AWS / GCP / on-prem / K8s 一致。</p>
<p>關鍵張力：低 FP 的 <em>代價</em> 是要花時間理解自家業務語意。Signature WAF 是「裝上就有保護」、Fastly NG-WAF 是「裝上有 baseline、業務 anomaly 要自己標」。沒有人定義 Tag + Power Rules、就只用到產品 30% 能力。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本頁、讀者能判斷：</p>
<ol>
<li>Fastly NG-WAF 的 Signal / Tag / Rule / Mode 四個核心 first-class concept 各承擔什麼責任</li>
<li>Edge / Agent + Module / Cloud Proxy 三種部署模型的選擇條件</li>
<li>Account Takeover Protection、Bot Protection、API discovery 三個進階 module 的適用情境</li>
<li>何時用 Fastly NG-WAF、何時走 <a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a> / <a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a> 的取捨</li>
</ol>
<h2 id="最短判讀路徑">最短判讀路徑</h2>
<p>判斷 Fastly NG-WAF 配置是否健康、最少看四件事：</p>
<ul>
<li><strong>部署模型對齊架構</strong>：Fastly Edge inline（流量本來就過 Fastly CDN）/ Agent + Module（自管 Nginx / Apache / IIS / Envoy / .NET 加 sigsci-agent local process）/ Cloud Proxy（Fastly 接 origin proxy）三選一或混用、是否覆蓋所有入口（含 admin、internal API、staging）</li>
<li><strong>Signal 與 Tag 設計</strong>：預設 Signal（SQLi / XSS / CMDI / Traversal / Backdoor / Anomaly）是否全開、業務語意 Tag（admin-path、internal-only、payment-flow）是否定義並掛上 Match Conditions、Power Rules 是否組合多 Signal / Tag 走 threshold-based action</li>
<li><strong>Rule mode 與 threshold</strong>：Site-level 跟 Corp-level Rule 是 Block 還是 Off、threshold（連續幾個 Signal / 多久窗口）是否依 endpoint 業務調整、Template Rule（ATO、Bot）是否啟用</li>
<li><strong>Logging 與 sigsci-agent token 治理</strong>：Syslog / HTTP webhook / S3 / SIEM（Splunk / Datadog / Sumo Logic）整合是否 production-grade、sigsci-agent 連回控制面的 token 是否進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、跨環境 token 是否分離</li>
</ul>
<p>四件事任一缺失、就是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a> 與 <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">Entry Point Protection</a> 邊界的待補項目。</p>
<h2 id="日常操作與決策形狀">日常操作與決策形狀</h2>
<p><strong>部署模型選擇</strong>：<em>Fastly Edge inline</em> 是最簡部署、流量已過 Fastly CDN 就 inline 加 NG-WAF、沒有額外 agent 要管；<em>Agent + Module</em> 是 self-managed Nginx / Apache / IIS / Envoy / HAProxy / .NET / Java（Tomcat）等加裝 sigsci-module（process 內 module 攔請求）+ sigsci-agent（本機 daemon、跟 Fastly 控制面 sync rule、collect event）— 適合 origin 不過 Fastly CDN、或 internal API；<em>Cloud Proxy</em> 是 Fastly 提供 reverse proxy 端點、客戶 DNS 指過去、origin 在後面 — 適合不想改 origin、又沒用 Fastly CDN。三種混用常見、大企業 edge 用 Fastly Edge、internal service 用 Agent + Module。</p>
<p><strong>Signal 是已知攻擊指標</strong>：Fastly NG-WAF 預定義 Signal 包含 <em>SQLi / XSS / CMDI（command injection）/ Traversal（路徑穿越）/ Backdoor / RCE / Anomaly</em> 等。Signal 是 <em>語意解析結果</em> — request body 被 parser 拆解（JSON / form / multipart）、每個欄位看「這像不像某類攻擊」、不是 regex 比對。意義是 <em>encoding 變化攔不住</em>（base64 / URL encode / Unicode normalize 都會被解開）、跟 signature WAF 的脆性對比明顯。</p>
<p><strong>Tag 是客戶自定 Signal</strong>：用 <em>Match Conditions</em>（path / method / IP / header / body content / query 參數）定義「什麼樣的請求叫某 tag」、例：<code>Path: /admin/* AND Source IP NOT IN internal_cidr → tag: admin-external-access</code>。Tag 之後可以走 Rule 處理（看到 admin-external-access 就 alert / block）。Tag 是 Fastly NG-WAF 表達 <em>業務語意</em> 的主要工具、不是用來補強 Signal。</p>
<p><strong>Rule 三層</strong>：<em>Site-level Rule</em>（單一 site / property）/ <em>Corp-level Rule</em>（整個 organization 共用、用於 corp-wide block list、跨 BU 統一 policy）/ <em>Template Rule</em>（Fastly 提供的預設複合 rule、如 ATO template、Bot template）。Rule 表達式組合 Signal / Tag / Source IP / Path / Method、走 Block / Off。Power Rules 是進階版 — 支援 <em>threshold</em> + <em>時間窗口</em> + <em>多條件 AND/OR</em>、例：「同 IP 在 60 秒內觸發 5 個 SQLi Signal 就 Block 10 分鐘」。</p>
<p><strong>Mode 兩種</strong>：<em>Block</em>（攔截、回 406 / 自訂 status）/ <em>Off</em>（不動作、純 log）。沒有 Cloudflare 的 Sensitivity 滑桿 — 因為 Signal 本身已是語意判讀結果、不需要敏感度調整、調整在 <em>threshold</em>（多少 Signal 才動作）。</p>
<p><strong>Account Takeover Protection（ATO）</strong>：偵測 credential stuffing pattern — 同 IP 多 login fail、跨 IP 同 account 多 login、impossible travel、unusual UA。Fastly NG-WAF 內建 <em>login endpoint detection</em>（自動 / 手動標記 <code>/login</code>、<code>/auth/signin</code> 等）、配合 ATO Template Rule 直接 inline 處理（rate limit、challenge、block）。對應 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity Boundary</a> 的 ATO 對策、但是在 WAF 層直接攔、不等 IdP 內 ATO 邏輯。</p>
<p><strong>Bot Protection</strong>：跟 Cloudflare Bot Management 同類、走 behavioral + browser fingerprint + JS challenge、區分 verified bot / likely bot / human。比 user-agent 過濾穩、headless browser 攔得住。</p>
<p><strong>API discovery</strong>：Fastly NG-WAF 自動學習 site 的 API endpoint 與 schema、偵測 <em>schema drift</em>（突然出現的多餘欄位、缺欄位、type mismatch）— 比手動維護 OpenAPI schema 輕量、適合內部 API 多但沒寫完整 OpenAPI 的團隊。</p>
<p><strong>Logging 與 sigsci-agent 治理</strong>：所有 event 走 Fastly NG-WAF 控制面 + 客戶端 Syslog / HTTP webhook / S3 / SIEM（Splunk / Datadog / Sumo Logic）。sigsci-agent 連回控制面用 <em>Site API key</em> — 該 key 進 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>、跨環境 prod / staging 分離、rotation 走標準 secret rotation 流程、不能寫死在 agent 配置檔。</p>
<h2 id="核心取捨表">核心取捨表</h2>
<table>
  <thead>
      <tr>
          <th>取捨維度</th>
          <th>Fastly Next-Gen WAF</th>
          <th>Cloudflare WAF</th>
          <th>AWS WAF</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>偵測模型</td>
          <td>Signal / 語意分析 / behavioral（低 FP）</td>
          <td>Signature + Managed Rule + ML</td>
          <td>Signature + Managed Rule + Lambda 自訂</td>
      </tr>
      <tr>
          <td>部署位置</td>
          <td>Fastly Edge / Agent + Module / Cloud Proxy</td>
          <td>Cloudflare global edge</td>
          <td>AWS region 內 ALB / CloudFront / API Gateway 前</td>
      </tr>
      <tr>
          <td>Block 模式可行性</td>
          <td>高 — 預設低 FP、production 可直開</td>
          <td>中 — 需 sensitivity tuning + Log Mode 觀察</td>
          <td>中 — managed rule FP 需排除、custom rule 自管</td>
      </tr>
      <tr>
          <td>業務語意表達</td>
          <td>Tag + Match Conditions + Power Rules（threshold）</td>
          <td>Custom Rule（Rules language）+ Bot Score</td>
          <td>JSON policy + Lambda 自訂</td>
      </tr>
      <tr>
          <td>自管伺服器支援</td>
          <td>強 — sigsci-agent + module 覆蓋 Nginx / Apache / IIS</td>
          <td>弱 — 必須流量過 Cloudflare edge</td>
          <td>弱 — 必須走 AWS service</td>
      </tr>
      <tr>
          <td>ATO 內建</td>
          <td>是 — Template Rule 直接 inline</td>
          <td>Exposed Credentials Check（部分覆蓋）</td>
          <td>AWS WAF Fraud Control（加價）</td>
      </tr>
      <tr>
          <td>Bot Protection</td>
          <td>內建（同層產品）</td>
          <td>加價 add-on（Pro / Business / Enterprise）</td>
          <td>AWS WAF Bot Control（加價）</td>
      </tr>
      <tr>
          <td>API discovery</td>
          <td>內建（auto schema learning）</td>
          <td>API Shield（Enterprise）</td>
          <td>API Gateway request validator</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>中 — Signal / Tag mindset 要轉、agent 安裝要熟</td>
          <td>中 — UI 易上手、Rules language 表達力強</td>
          <td>較陡 — JSON policy + 多 AWS service 整合</td>
      </tr>
      <tr>
          <td>價格</td>
          <td>較高 — Enterprise tier 為主、按請求量計</td>
          <td>分層（Free / Pro / Business / Enterprise）</td>
          <td>按 rule + request 量、起步低</td>
      </tr>
      <tr>
          <td>適合場景</td>
          <td>低 FP 要求、API 重、自管伺服器多、跨雲 / on-prem</td>
          <td>多雲 / on-prem origin、要整套 edge security suite</td>
          <td>AWS-heavy、ALB / CloudFront / API Gateway 是主入口</td>
      </tr>
  </tbody>
</table>
<p>選 Fastly NG-WAF 的核心訴求：<em>production 直接 Block</em> + <em>API / schema-rich 業務</em> + <em>自管伺服器需要 inline agent</em> + <em>跨雲 / on-prem mix</em>、且有預算支付 Enterprise tier。純 AWS-internal 簡單 web app 用 AWS WAF 整合更直接；要整套 edge security suite 用 Cloudflare。</p>
<h2 id="進階主題">進階主題</h2>
<p><strong>VCL + Edge custom rule</strong>：Fastly Edge 部署模式下、NG-WAF 跟 <a href="https://www.fastly.com/">Fastly CDN</a> 的 VCL（Varnish Configuration Language）共存、複雜邏輯可寫 VCL 在 NG-WAF 處理前後攔截 — 例：geo block 在 VCL 做、NG-WAF 處理通過的請求。Compute@Edge（Fastly 的 edge serverless、類 Cloudflare Workers）也可以接 NG-WAF 結果做進一步處理。代價是 VCL / Compute@Edge code 變另一條 ops trace、要有版控與 staging。</p>
<p><strong>ATO 進階 — credential stuffing 場景</strong>：login endpoint 接 ATO Template Rule 後、可進一步整合 <em>已洩漏 credential check</em>（類 Have I Been Pwned 整合）、failed login burst → progressive challenge（先 CAPTCHA、再 block）。對應 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">Identity Boundary</a> 的 IdP ATO 邏輯、Fastly 在 WAF 層攔的好處是 <em>攻擊不會打到 IdP</em>、減少 IdP 端 rate limit 壓力。</p>
<p><strong>Bot Protection 進階</strong>：browser fingerprint + behavioral pattern + JS challenge 三層、可掛 <em>bot score threshold</em> 在 Power Rules 內、配合 ATO 做 <em>high-risk login flow</em>（bot score 高 + login endpoint → 強 challenge）。</p>
<p><strong>Agent + Module 在 K8s / VM</strong>：K8s 場景 sigsci-agent 走 sidecar 或 DaemonSet、sigsci-module 在 ingress controller（Nginx Ingress Controller 加 sigsci-nginx module）；VM 場景 sigsci-agent 走 systemd service、module 隨 web server 啟動。跨環境 token 隔離（prod / staging / dev）走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a> dynamic secret 或環境變數注入、不寫死配置檔。</p>
<p><strong>Corp-level Rule 共用</strong>：多 BU / 多產品線在同一 Corp（Fastly NG-WAF 的 organization 概念）下、Corp Rule 跨所有 Site 生效 — 適合表達「全公司禁 IP X」「全公司 ATO Template 都開」、避免每個 Site 重複配置。</p>
<h2 id="排錯與失敗快速判讀">排錯與失敗快速判讀</h2>
<ul>
<li><strong>Signal 沒觸發、攻擊穿過</strong>：Encoding 異常 / parser 沒解析該 content-type — 確認 Content-Type 正確、body 大小沒超過 sigsci-module 限制（預設 100KB）、Signal scope 是否包含該 endpoint</li>
<li><strong>Tag 沒掛上</strong>：Match Conditions 寫錯（path 大小寫、trailing slash、wildcard 語意）— 在 Fastly NG-WAF console 用 <em>Rule Evaluation</em> 工具測試 request 是否命中</li>
<li><strong>Block 模式誤殺</strong>：Power Rules threshold 太低、單一合法請求觸發多 Signal — 調 threshold 或加 Site Rule exception 排除特定 path / source</li>
<li><strong>sigsci-agent 跟控制面失聯</strong>：Site API key 過期 / firewall block out-bound / agent 版本太舊 — agent log 看 connection status、輪換 token 走 <a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">Vault</a>、保持 agent 在 supported version range</li>
<li><strong>sigsci-module load 失敗</strong>：web server 啟動報 module 載入錯 — 確認 module 版本跟 web server major version 對齊（Nginx 1.20 對 sigsci-nginx 對應版本）</li>
<li><strong>ATO Template 沒攔到</strong>：login endpoint detection 沒標到自家 path — 手動在 console 標記 login endpoint 路徑</li>
<li><strong>Logging gap</strong>：Syslog / webhook 送失敗、SIEM 沒收到 — 確認 destination accept、TLS cert 沒過期、retry policy</li>
<li><strong>跨環境 token 漏氣</strong>：staging token 流到 prod、改 staging 影響 prod rule — Vault 環境分離、token 加標籤、定期 audit token usage</li>
</ul>
<h2 id="何時改走其他服務">何時改走其他服務</h2>
<table>
  <thead>
      <tr>
          <th>需求形狀</th>
          <th>改走</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>AWS-only + ALB / CloudFront origin</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></td>
      </tr>
      <tr>
          <td>多雲 + 要整套 edge security suite</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a></td>
      </tr>
      <tr>
          <td>純 internal mTLS / east-west</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/spire/" data-link-title="SPIRE" data-link-desc="SPIFFE Runtime Environment、attested workload identity、short-lived SVID &#43; Trust Bundle、跨組織 federation">SPIRE</a> + service mesh</td>
      </tr>
      <tr>
          <td>Cert lifecycle</td>
          <td><a href="/blog/backend/07-security-data-protection/vendors/cert-manager/" data-link-title="cert-manager" data-link-desc="K8s 原生 certificate lifecycle automation、支援 Let&#39;s Encrypt / Vault PKI / Venafi 等多 issuer、auto-renewal &#43; Challenge solver">cert-manager</a> / <a href="/blog/backend/07-security-data-protection/vendors/letsencrypt/" data-link-title="Let&#39;s Encrypt" data-link-desc="免費 &#43; 自動化的公共 ACME CA、90 天 TTL 強制自動化、跨雲跨平台 public TLS cert 的事實基礎">Let&rsquo;s Encrypt</a></td>
      </tr>
      <tr>
          <td>Bot management 為主要訴求、預算敏感</td>
          <td>Cloudflare Bot Management 入門 / AWS WAF Bot Control</td>
      </tr>
      <tr>
          <td>DDoS L3/L4 為主</td>
          <td>Cloudflare Magic Transit / AWS Shield Advanced</td>
      </tr>
  </tbody>
</table>
<h2 id="不在本頁內的主題">不在本頁內的主題</h2>
<ul>
<li>Signal Sciences 收購前的 product line 演進細節</li>
<li>完整 Signal 清單與每個 Signal 的內部解析邏輯</li>
<li>VCL / Compute@Edge 完整語法 reference</li>
<li>Fastly CDN 本身的 caching / TLS / origin shielding 細節</li>
<li>Enterprise 合約細節、各國資料駐留選項</li>
</ul>
<h2 id="案例回寫">案例回寫</h2>
<p>Fastly NG-WAF 沒有直接 vendor-level 公開事件、案例庫對照引用以「behavioral detection 在 zero-day / supply chain 場景的 inline mitigation 角色」為主：</p>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>跟 Fastly NG-WAF 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/supply-chain/log4shell-cve-2021-44228-component-chain/" data-link-title="7.R7.2.7 Log4Shell 2021：共用元件風險與修補鏈" data-link-desc="共用元件漏洞如何同步影響多服務，並迫使團隊建立依賴治理 workflow">Log4Shell CVE-2021-44228</a></td>
          <td>對照啟示 — Anomaly Signal 對 JNDI pattern 有 immediate inline detection、不需等 vendor signature 更新；但 exploitation 進後端後仍要靠 supply chain 治理</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/citrix-bleed-2023-session-hijack/" data-link-title="7.R7.3.3 Citrix Bleed 2023：會話被劫持與重放風險" data-link-desc="邊界設備會話資料外洩後，如何演變成帳號與服務風險">Citrix Bleed 2023 Session Hijack</a></td>
          <td>對照啟示 — WAF 攔不住 edge appliance zero-day、需要「修補 + session 失效 + 異常清查」三同步、NG-WAF Power Rules 可在窗口期提供臨時 anomaly 偵測</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/red-team/cases/edge-exposure/fortinet-cve-2023-27997-sslvpn-overflow/" data-link-title="7.R7.3.21 Fortinet 2023：CVE-2023-27997 SSL-VPN 溢位" data-link-desc="SSL-VPN 漏洞在邊界設備上會放大大規模掃描與利用速度">Fortinet SSL-VPN CVE 2023-27997</a></td>
          <td>對照啟示 — vendor patch 前用 Power Rules + Tag 快速部署臨時 mitigation、收斂可達來源是修補窗口期的標準動作</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></td>
          <td>Fastly NG-WAF 是 entry point protection 的工具、低 FP 設計讓 production Block 模式可行、跟 signature WAF 的部署成本曲線根本不同</td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>上游：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>平行：<a href="/blog/backend/07-security-data-protection/vendors/cloudflare-waf/" data-link-title="Cloudflare WAF" data-link-desc="Edge WAF &#43; DDoS &#43; Bot management 整合套件、global anycast 網路、控制面信任邊界跟客戶側補強的對照">Cloudflare WAF</a>、<a href="/blog/backend/07-security-data-protection/vendors/aws-waf/" data-link-title="AWS WAF" data-link-desc="AWS-internal WAF、跟 ALB / CloudFront / API Gateway 直接整合、Web ACL &#43; Managed Rule Group &#43; Rate-based Rule、Shield Standard 內含">AWS WAF</a></li>
<li>下游：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a>（WAF block 不夠時、資料層也要遮罩）</li>
<li>跨類：<a href="/blog/backend/07-security-data-protection/vendors/hashicorp-vault/" data-link-title="HashiCorp Vault" data-link-desc="Self-hosted secret management 與 dynamic credential / encryption-as-a-service / PKI engine、跨雲跨環境的 secret 控制面">HashiCorp Vault</a>（sigsci-agent Site API key 存放）、<a href="/blog/backend/07-security-data-protection/vendors/okta/" data-link-title="Okta" data-link-desc="SaaS Identity Provider 主流選項、SSO / MFA / lifecycle 整合、第三方信任邊界的代價">Okta</a>（Fastly admin 走 SSO）</li>
<li>跨模組：<a href="/blog/backend/08-incident-response/vendors/" data-link-title="事故處理 Vendor 清單" data-link-desc="規劃 on-call、incident response、status page 與 postmortem 工具的服務頁撰寫順序與判準">8 事故處理 vendor 清單</a>（WAF block 事件 routing 進 IR）</li>
<li>官方：<a href="https://docs.fastly.com/products/next-gen-waf">Fastly Next-Gen WAF Documentation</a></li>
</ul>
]]></content:encoded></item><item><title>SQLite D1 / Turso / libSQL Comparison</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/d1-turso-libsql-comparison/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/d1-turso-libsql-comparison/</guid><description>&lt;p>D1 / Turso / libSQL comparison 的核心責任是把 SQLite-compatible edge products 和 local SQLite 分開判讀。它們共享 SQLite 開發體驗的一部分，但它們承擔的服務責任不同：Cloudflare D1 把 SQLite-like database 放進 Workers 生態與 managed edge platform；Turso / libSQL 把 SQLite family 延伸到 remote primary、embedded replica 與同步模型；local SQLite 則是 application process 直接管理單一 database file。&lt;/p>
&lt;p>本文的判讀錨點是：SQLite compatibility 代表開發入口接近，服務責任仍要重新審查。採用 edge SQLite 前，要先確認 write authority、read freshness、migration limit、backup evidence、observability、cost 與 vendor exit，而非只看 SQL 語法能否執行。&lt;/p>
&lt;h2 id="product-boundary">Product Boundary&lt;/h2>
&lt;p>Product boundary 的核心責任是定義誰持有資料、誰執行 SQL、誰負責恢復。Local SQLite 的資料在你的 filesystem；D1 的資料由 Cloudflare D1 平台管理並和 Workers binding 整合；Turso / libSQL 的資料通常有 remote database 與 client / embedded replica 的分工。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>選項&lt;/th>
 &lt;th>主要責任&lt;/th>
 &lt;th>適合情境&lt;/th>
 &lt;th>關鍵審查點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Local SQLite&lt;/td>
 &lt;td>Process-local formal state&lt;/td>
 &lt;td>CLI、desktop、single-node app&lt;/td>
 &lt;td>file lifecycle、backup、WAL、lock&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloudflare D1&lt;/td>
 &lt;td>Workers-integrated database&lt;/td>
 &lt;td>edge app、serverless API、low ops&lt;/td>
 &lt;td>platform limit、migration、binding&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Turso / libSQL&lt;/td>
 &lt;td>Remote primary + replicas&lt;/td>
 &lt;td>low-latency read、embedded replica&lt;/td>
 &lt;td>freshness、sync、driver semantics&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Litestream / LiteFS&lt;/td>
 &lt;td>Backup / replica operation&lt;/td>
 &lt;td>single-node app with recovery / read&lt;/td>
 &lt;td>RPO、RTO、primary ownership&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PostgreSQL&lt;/td>
 &lt;td>Server SQL operation&lt;/td>
 &lt;td>multi-tenant、central audit、HA、role&lt;/td>
 &lt;td>operation team、PITR、schema gate&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Local SQLite 的判斷重點是 file ownership。若 app 與 database file 位於同一個 host，備份、restore、disk full、permission 與 app upgrade 都在你的 runbook 裡；這條路線承接 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/file-lifecycle-backup-boundary/" data-link-title="SQLite file lifecycle 與 backup boundary" data-link-desc="把 SQLite 單檔案正式狀態拆成 WAL、backup API、restore drill、corruption recovery 與操作責任邊界">file lifecycle / backup boundary&lt;/a>。&lt;/p>
&lt;p>D1 的判斷重點是 platform integration。Cloudflare 官方 D1 docs 把 D1 放在 Workers 與 Wrangler workflow 內，並公開 &lt;a href="https://developers.cloudflare.com/d1/platform/limits/">D1 limits&lt;/a>；因此採用 D1 時要把 database decision 與 Workers deployment、local preview、batch migration、import/export limit 一起審查。&lt;/p></description><content:encoded><![CDATA[<p>D1 / Turso / libSQL comparison 的核心責任是把 SQLite-compatible edge products 和 local SQLite 分開判讀。它們共享 SQLite 開發體驗的一部分，但它們承擔的服務責任不同：Cloudflare D1 把 SQLite-like database 放進 Workers 生態與 managed edge platform；Turso / libSQL 把 SQLite family 延伸到 remote primary、embedded replica 與同步模型；local SQLite 則是 application process 直接管理單一 database file。</p>
<p>本文的判讀錨點是：SQLite compatibility 代表開發入口接近，服務責任仍要重新審查。採用 edge SQLite 前，要先確認 write authority、read freshness、migration limit、backup evidence、observability、cost 與 vendor exit，而非只看 SQL 語法能否執行。</p>
<h2 id="product-boundary">Product Boundary</h2>
<p>Product boundary 的核心責任是定義誰持有資料、誰執行 SQL、誰負責恢復。Local SQLite 的資料在你的 filesystem；D1 的資料由 Cloudflare D1 平台管理並和 Workers binding 整合；Turso / libSQL 的資料通常有 remote database 與 client / embedded replica 的分工。</p>
<table>
  <thead>
      <tr>
          <th>選項</th>
          <th>主要責任</th>
          <th>適合情境</th>
          <th>關鍵審查點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Local SQLite</td>
          <td>Process-local formal state</td>
          <td>CLI、desktop、single-node app</td>
          <td>file lifecycle、backup、WAL、lock</td>
      </tr>
      <tr>
          <td>Cloudflare D1</td>
          <td>Workers-integrated database</td>
          <td>edge app、serverless API、low ops</td>
          <td>platform limit、migration、binding</td>
      </tr>
      <tr>
          <td>Turso / libSQL</td>
          <td>Remote primary + replicas</td>
          <td>low-latency read、embedded replica</td>
          <td>freshness、sync、driver semantics</td>
      </tr>
      <tr>
          <td>Litestream / LiteFS</td>
          <td>Backup / replica operation</td>
          <td>single-node app with recovery / read</td>
          <td>RPO、RTO、primary ownership</td>
      </tr>
      <tr>
          <td>PostgreSQL</td>
          <td>Server SQL operation</td>
          <td>multi-tenant、central audit、HA、role</td>
          <td>operation team、PITR、schema gate</td>
      </tr>
  </tbody>
</table>
<p>Local SQLite 的判斷重點是 file ownership。若 app 與 database file 位於同一個 host，備份、restore、disk full、permission 與 app upgrade 都在你的 runbook 裡；這條路線承接 <a href="/blog/backend/01-database/vendors/sqlite/file-lifecycle-backup-boundary/" data-link-title="SQLite file lifecycle 與 backup boundary" data-link-desc="把 SQLite 單檔案正式狀態拆成 WAL、backup API、restore drill、corruption recovery 與操作責任邊界">file lifecycle / backup boundary</a>。</p>
<p>D1 的判斷重點是 platform integration。Cloudflare 官方 D1 docs 把 D1 放在 Workers 與 Wrangler workflow 內，並公開 <a href="https://developers.cloudflare.com/d1/platform/limits/">D1 limits</a>；因此採用 D1 時要把 database decision 與 Workers deployment、local preview、batch migration、import/export limit 一起審查。</p>
<p>Turso / libSQL 的判斷重點是 replica freshness 與 client semantics。Turso docs 對 <a href="https://docs.turso.tech/features/embedded-replicas/introduction">embedded replicas</a> 的描述顯示：application 可以持有 local replica 並透過同步取得資料；這會把「讀得快」和「讀到多新」變成同一個設計問題。</p>
<h2 id="edge-data-model">Edge Data Model</h2>
<p>Edge data model 的核心責任是把 latency 改善與一致性責任拆開。Edge database 的價值常來自 closer read path、serverless deployment 與較低操作表面；風險則集中在 write authority、replication lag、region routing 與平台限制。</p>
<table>
  <thead>
      <tr>
          <th>問題</th>
          <th>要觀察的訊號</th>
          <th>設計含義</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>誰可以寫</td>
          <td>single primary、remote write、queue</td>
          <td>決定 conflict、retry、idempotency 設計</td>
      </tr>
      <tr>
          <td>讀取要多新</td>
          <td>read-after-write、sync interval</td>
          <td>決定 UI freshness、cache invalidation、fallback</td>
      </tr>
      <tr>
          <td>migration 怎麼跑</td>
          <td>CLI、batch limit、preview / prod gap</td>
          <td>決定 release gate 與 rollback plan</td>
      </tr>
      <tr>
          <td>失敗時如何恢復</td>
          <td>export、backup、restore command</td>
          <td>決定 RPO / RTO 與 vendor exit</td>
      </tr>
      <tr>
          <td>observability 在哪一層</td>
          <td>platform metrics、app log、query log</td>
          <td>決定 incident triage 從 app 還是 platform 開始查</td>
      </tr>
  </tbody>
</table>
<p>Write authority 是 edge SQLite 的第一個分水嶺。若所有 write 都集中到 remote primary，application 要處理 network error、retry、idempotency 與 read freshness；若 write 發生在 local replica，系統要有 conflict resolution、sync ordering 與 delete propagation。</p>
<p>Read locality 是 edge SQLite 的主要收益。它適合 session-local preference、read-mostly catalog、低風險 personalization、feature flag snapshot、tenant-local small dataset；這些情境的共同點是資料量小、write rate 低、freshness 可以定義。</p>
<p>Global transaction 是 edge SQLite 的高風險區。若產品需求包含跨 region balance transfer、inventory reservation、ledger posting、strongly consistent permission decision，設計應路由到 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">Global Distributed OLTP</a> 或 PostgreSQL / CockroachDB / Spanner 的 transactional model。</p>
<h2 id="migration-gap">Migration Gap</h2>
<p>Migration gap 的核心責任是確認 SQLite file 可以搬到 edge product 後，release workflow 仍可驗證。SQL syntax compatibility 只解決起點；真正會造成事故的是 batch limit、extension 差異、driver API、local preview 與 production platform 行為差異。</p>
<table>
  <thead>
      <tr>
          <th>差異面</th>
          <th>審查問題</th>
          <th>Evidence</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SQL dialect</td>
          <td>schema、index、trigger、JSON 是否可用</td>
          <td>compatibility matrix + migration dry run</td>
      </tr>
      <tr>
          <td>Data movement</td>
          <td>seed / import / export 的容量與時間</td>
          <td>sample import、row count、checksum</td>
      </tr>
      <tr>
          <td>Runtime binding</td>
          <td>app 如何取得 database connection</td>
          <td>staging deployment + smoke test</td>
      </tr>
      <tr>
          <td>Transaction</td>
          <td>write path 是否跨 request / region</td>
          <td>failure injection、retry log、freshness test</td>
      </tr>
      <tr>
          <td>Backup / exit</td>
          <td>如何拿回 SQLite-compatible artifact</td>
          <td>export file、restore drill、retention note</td>
      </tr>
  </tbody>
</table>
<p>D1 migration 要把 Wrangler workflow 納入 release gate。Cloudflare D1 的 limits 文件明確列出 import、query、batch 等限制；因此大型 update / delete 要拆 batch，migration 要有 staging dry run 與 production rollback step。</p>
<p>Turso / libSQL migration 要把 driver semantics 納入 release gate。Local SQLite driver 直連 file；libSQL client 可能連 remote endpoint 或 embedded replica；application 要把 connection lifecycle、sync timing、auth token、network failure 與 local cache freshness 寫進測試。</p>
<h2 id="operational-model">Operational Model</h2>
<p>Operational model 的核心責任是把 managed convenience 轉成 ownership map。Edge SQLite 減少了部分 server operation，但新增 platform limit、billing、region behavior、vendor incident、CLI workflow 與 local preview mismatch。</p>
<p>Production runbook 至少要保存五種證據：</p>
<ol>
<li>Schema migration history 與每次 release 的 dry-run result。</li>
<li>Data import / export 指令、檔案大小、row count 與 checksum。</li>
<li>Region latency、read freshness、write error rate 與 retry count。</li>
<li>Platform limit 命中紀錄、batch policy 與成本警戒線。</li>
<li>Vendor exit route：回 local SQLite、PostgreSQL 或另一個 edge database 的最小搬遷步驟。</li>
</ol>
<p>成本模型要同時看 request、storage、egress、operation time 與工程鎖定。Edge product 常把起步成本壓低，但當資料變大、batch migration 變長、observability 需要外掛、vendor API 滲入 repository layer 時，長期成本會出現在 release 與 incident。</p>
<h2 id="decision-route">Decision Route</h2>
<p>Decision route 的核心責任是把需求送到相符的資料模型。D1 / Turso / libSQL 適合 edge locality 與低操作表面；當需求轉向 high-write OLTP、central audit、role-based permission、global transaction 或跨服務資料治理，應轉向 server SQL 或 distributed OLTP。</p>
<table>
  <thead>
      <tr>
          <th>需求訊號</th>
          <th>優先路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Workers app 需要小型 relational data</td>
          <td>Cloudflare D1 + explicit limits review</td>
      </tr>
      <tr>
          <td>App 需要 local read latency + remote sync</td>
          <td>Turso / libSQL + freshness contract</td>
      </tr>
      <tr>
          <td>Single-node app 只需要備份與恢復</td>
          <td>Local SQLite + <a href="/blog/backend/01-database/vendors/sqlite/litestream-litefs-replication/" data-link-title="SQLite Litestream / LiteFS Replication" data-link-desc="Litestream、LiteFS、SQLite backup replication、read replica、failover 與 restore route">Litestream / LiteFS</a></td>
      </tr>
      <tr>
          <td>多 tenant、central audit、DB role</td>
          <td><a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL</a></td>
      </tr>
      <tr>
          <td>Global write consistency</td>
          <td><a href="/blog/backend/01-database/vendors/cockroachdb/" data-link-title="CockroachDB" data-link-desc="分散式 SQL、PostgreSQL 相容、跨區強一致、Spanner 的開源 / 跨雲替代">CockroachDB</a> 或 Spanner</td>
      </tr>
  </tbody>
</table>
<p>D1 的採用條件是 edge runtime 本身就是主平台。若 application 已在 Workers 上、資料量可控、query pattern 清楚、migration 可 batch，D1 可以把 database operation 融入 deployment workflow。</p>
<p>Turso / libSQL 的採用條件是 local read value 高於同步複雜度。若產品可明確定義 stale read window、write path 與 conflict policy，embedded replica 可以降低 latency；若使用者需要立即看見跨裝置變更，就要先設計 freshness evidence。</p>
<h2 id="production-tripwires">Production Tripwires</h2>
<p>Production tripwires 的核心責任是指出何時重新評估 edge SQLite。這些訊號出現時，系統通常已從「SQLite-compatible convenience」進入正式 database governance。</p>
<table>
  <thead>
      <tr>
          <th>Tripwire</th>
          <th>意義</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Migration batch 經常碰 limit</td>
          <td>schema 與資料量超過 edge workflow</td>
          <td>評估 PostgreSQL / managed SQL</td>
      </tr>
      <tr>
          <td>Read freshness ticket 增加</td>
          <td>replica / sync 語意影響產品體驗</td>
          <td>建 freshness SLO 或改集中讀寫</td>
      </tr>
      <tr>
          <td>Export / restore 未演練</td>
          <td>vendor exit 與災難恢復缺 evidence</td>
          <td>補 restore drill 與 retention policy</td>
      </tr>
      <tr>
          <td>Driver API 滲入 domain</td>
          <td><a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">vendor lock-in</a> 進入核心程式碼</td>
          <td>建 repository adapter 與 compatibility test</td>
      </tr>
      <tr>
          <td>Cross-region write 需求出現</td>
          <td>edge-local read 已不足</td>
          <td>路由到 distributed OLTP</td>
      </tr>
  </tbody>
</table>
<p>這些 tripwire 要寫進設計文件與 runbook。Edge SQLite 的優勢在於低摩擦起步；它的長期品質來自早期把 ownership、limits、exit 與 evidence 設計清楚。</p>
<h2 id="下一步路由">下一步路由</h2>
<p>D1 / Turso / libSQL comparison 完成後，下一步要依壓力路由。要處理 local file 與 backup，讀 <a href="/blog/backend/01-database/vendors/sqlite/file-lifecycle-backup-boundary/" data-link-title="SQLite file lifecycle 與 backup boundary" data-link-desc="把 SQLite 單檔案正式狀態拆成 WAL、backup API、restore drill、corruption recovery 與操作責任邊界">file lifecycle / backup boundary</a>；要處理 replica / restore，讀 <a href="/blog/backend/01-database/vendors/sqlite/litestream-litefs-replication/" data-link-title="SQLite Litestream / LiteFS Replication" data-link-desc="Litestream、LiteFS、SQLite backup replication、read replica、failover 與 restore route">Litestream / LiteFS replication</a>；要從 local SQLite 移到 edge product，讀 <a href="/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/" data-link-title="SQLite to D1 / Turso Migration" data-link-desc="SQLite 轉向 Cloudflare D1、Turso / libSQL 的 edge driver、compatibility audit、data movement 與 rollback">SQLite to D1 / Turso migration</a>；要處理 global write，回到 <a href="/blog/backend/01-database/global-distributed-oltp/" data-link-title="1.11 全球分散式 OLTP" data-link-desc="Spanner / Aurora DSQL / Cosmos DB multi-region write / CockroachDB / TiDB 的全球一致性取捨">Global Distributed OLTP</a>。</p>
]]></content:encoded></item><item><title>SQLite D1 / Turso Preview Lab</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/hands-on/d1-turso-preview-lab/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/hands-on/d1-turso-preview-lab/</guid><description>&lt;p>SQLite D1 / Turso preview lab 的核心責任是把 local SQLite 轉向 edge SQLite product 前的 compatibility gap 找出來。這篇承接 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/d1-turso-libsql-comparison/" data-link-title="SQLite D1 / Turso / libSQL Comparison" data-link-desc="Cloudflare D1、Turso、libSQL 與 local SQLite 在 edge、replication、consistency、migration 與 vendor boundary 的比較">D1 / Turso / libSQL Comparison&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/" data-link-title="SQLite to D1 / Turso Migration" data-link-desc="SQLite 轉向 Cloudflare D1、Turso / libSQL 的 edge driver、compatibility audit、data movement 與 rollback">SQLite to D1 / Turso Migration&lt;/a>，把 edge migration 變成可回報的 query matrix。&lt;/p>
&lt;p>本文的驗收標準是：你能從 local SQLite 匯出 schema / seed，匯入 D1 或 Turso preview database，跑相同 query set，記錄 unsupported SQL、latency、error mapping 與 rollback route。&lt;/p>
&lt;h2 id="preview-scope">Preview Scope&lt;/h2>
&lt;p>Preview scope 的核心責任是把 lab 限制在 staging / preview。D1 與 Turso 都是平台產品，實際命令會依 CLI version、帳號、region 與專案設定改變；本文提供操作骨架與 evidence 格式，正式命令以官方文件為準。&lt;/p>
&lt;p>官方文件路由：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>產品&lt;/th>
 &lt;th>官方文件&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Cloudflare D1&lt;/td>
 &lt;td>&lt;a href="https://developers.cloudflare.com/d1/">Cloudflare D1 docs&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>D1 limits&lt;/td>
 &lt;td>&lt;a href="https://developers.cloudflare.com/d1/platform/limits/">Cloudflare D1 limits&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Turso&lt;/td>
 &lt;td>&lt;a href="https://docs.turso.tech/">Turso docs&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Turso embedded replicas&lt;/td>
 &lt;td>&lt;a href="https://docs.turso.tech/features/embedded-replicas/introduction">Embedded replicas&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Preview lab 要先確認資料不含 production PII。若 seed data 來自正式資料，先做 masking 或 synthetic data。&lt;/p>
&lt;h2 id="export-local-sqlite">Export Local SQLite&lt;/h2>
&lt;p>Export local SQLite 的核心責任是建立 target platform 的 seed input。沿用 &lt;code>/tmp/sqlite-lab/app.db&lt;/code> 或 migration fixture。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">mkdir -p /tmp/sqlite-edge-lab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="nb">cd&lt;/span> /tmp/sqlite-edge-lab
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">cp /tmp/sqlite-lab/app.db ./app.db
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">sqlite3 app.db &lt;span class="s2">&amp;#34;.schema&amp;#34;&lt;/span> &amp;gt; schema.sql
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">sqlite3 app.db &lt;span class="s2">&amp;#34;.dump&amp;#34;&lt;/span> &amp;gt; seed.sql
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">sqlite3 app.db &lt;span class="s2">&amp;#34;SELECT COUNT(*) FROM accounts;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">sqlite3 app.db &lt;span class="s2">&amp;#34;SELECT COUNT(*) FROM ledger_entries;&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>schema.sql&lt;/code> 用來審查 DDL，&lt;code>seed.sql&lt;/code> 用來匯入 preview database。正式 migration 可能要拆 schema / data / index，並處理 target platform limits。&lt;/p>
&lt;h2 id="build-query-matrix">Build Query Matrix&lt;/h2>
&lt;p>Build query matrix 的核心責任是定義 preview 要驗證什麼。query set 要代表產品行為，而非只跑一個 &lt;code>SELECT 1&lt;/code>。&lt;/p></description><content:encoded><![CDATA[<p>SQLite D1 / Turso preview lab 的核心責任是把 local SQLite 轉向 edge SQLite product 前的 compatibility gap 找出來。這篇承接 <a href="/blog/backend/01-database/vendors/sqlite/d1-turso-libsql-comparison/" data-link-title="SQLite D1 / Turso / libSQL Comparison" data-link-desc="Cloudflare D1、Turso、libSQL 與 local SQLite 在 edge、replication、consistency、migration 與 vendor boundary 的比較">D1 / Turso / libSQL Comparison</a> 與 <a href="/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/" data-link-title="SQLite to D1 / Turso Migration" data-link-desc="SQLite 轉向 Cloudflare D1、Turso / libSQL 的 edge driver、compatibility audit、data movement 與 rollback">SQLite to D1 / Turso Migration</a>，把 edge migration 變成可回報的 query matrix。</p>
<p>本文的驗收標準是：你能從 local SQLite 匯出 schema / seed，匯入 D1 或 Turso preview database，跑相同 query set，記錄 unsupported SQL、latency、error mapping 與 rollback route。</p>
<h2 id="preview-scope">Preview Scope</h2>
<p>Preview scope 的核心責任是把 lab 限制在 staging / preview。D1 與 Turso 都是平台產品，實際命令會依 CLI version、帳號、region 與專案設定改變；本文提供操作骨架與 evidence 格式，正式命令以官方文件為準。</p>
<p>官方文件路由：</p>
<table>
  <thead>
      <tr>
          <th>產品</th>
          <th>官方文件</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cloudflare D1</td>
          <td><a href="https://developers.cloudflare.com/d1/">Cloudflare D1 docs</a></td>
      </tr>
      <tr>
          <td>D1 limits</td>
          <td><a href="https://developers.cloudflare.com/d1/platform/limits/">Cloudflare D1 limits</a></td>
      </tr>
      <tr>
          <td>Turso</td>
          <td><a href="https://docs.turso.tech/">Turso docs</a></td>
      </tr>
      <tr>
          <td>Turso embedded replicas</td>
          <td><a href="https://docs.turso.tech/features/embedded-replicas/introduction">Embedded replicas</a></td>
      </tr>
  </tbody>
</table>
<p>Preview lab 要先確認資料不含 production PII。若 seed data 來自正式資料，先做 masking 或 synthetic data。</p>
<h2 id="export-local-sqlite">Export Local SQLite</h2>
<p>Export local SQLite 的核心責任是建立 target platform 的 seed input。沿用 <code>/tmp/sqlite-lab/app.db</code> 或 migration fixture。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mkdir -p /tmp/sqlite-edge-lab
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nb">cd</span> /tmp/sqlite-edge-lab
</span></span><span class="line"><span class="ln">3</span><span class="cl">cp /tmp/sqlite-lab/app.db ./app.db
</span></span><span class="line"><span class="ln">4</span><span class="cl">sqlite3 app.db <span class="s2">&#34;.schema&#34;</span> &gt; schema.sql
</span></span><span class="line"><span class="ln">5</span><span class="cl">sqlite3 app.db <span class="s2">&#34;.dump&#34;</span> &gt; seed.sql
</span></span><span class="line"><span class="ln">6</span><span class="cl">sqlite3 app.db <span class="s2">&#34;SELECT COUNT(*) FROM accounts;&#34;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">sqlite3 app.db <span class="s2">&#34;SELECT COUNT(*) FROM ledger_entries;&#34;</span></span></span></code></pre></div><p><code>schema.sql</code> 用來審查 DDL，<code>seed.sql</code> 用來匯入 preview database。正式 migration 可能要拆 schema / data / index，並處理 target platform limits。</p>
<h2 id="build-query-matrix">Build Query Matrix</h2>
<p>Build query matrix 的核心責任是定義 preview 要驗證什麼。query set 要代表產品行為，而非只跑一個 <code>SELECT 1</code>。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Q1 list account balances
</span></span><span class="line"><span class="ln">2</span><span class="cl">Q2 insert ledger entry with unique idempotency key
</span></span><span class="line"><span class="ln">3</span><span class="cl">Q3 insert duplicate idempotency key and capture error
</span></span><span class="line"><span class="ln">4</span><span class="cl">Q4 foreign key violation
</span></span><span class="line"><span class="ln">5</span><span class="cl">Q5 transaction rollback
</span></span><span class="line"><span class="ln">6</span><span class="cl">Q6 pagination by created_at
</span></span><span class="line"><span class="ln">7</span><span class="cl">Q7 explain / performance sample if platform supports it</span></span></code></pre></div><p>這份 matrix 要保存 expected result。Local SQLite 先跑一次，把 row count、error category、latency baseline 記下來。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sqlite3 app.db <span class="s">&lt;&lt;&#39;SQL&#39;
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="s">.timer on
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="s">SELECT a.id, a.owner_name, SUM(l.amount_cents) AS balance_cents
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="s">FROM accounts a
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="s">JOIN ledger_entries l ON l.account_id = a.id
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="s">GROUP BY a.id, a.owner_name
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="s">ORDER BY a.id;
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="s">SQL</span></span></span></code></pre></div><h2 id="import-to-d1-preview">Import to D1 Preview</h2>
<p>Import to D1 preview 的核心責任是驗證 Cloudflare D1 workflow。以下是操作骨架，正式命令與 flags 以 Cloudflare D1 docs 和 Wrangler 版本為準。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Example shape only. Use your project naming and official Wrangler docs.</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">wrangler d1 create sqlite_edge_preview
</span></span><span class="line"><span class="ln">3</span><span class="cl">wrangler d1 execute sqlite_edge_preview --file<span class="o">=</span>seed.sql
</span></span><span class="line"><span class="ln">4</span><span class="cl">wrangler d1 execute sqlite_edge_preview --command<span class="o">=</span><span class="s2">&#34;SELECT COUNT(*) FROM accounts;&#34;</span></span></span></code></pre></div><p>D1 preview evidence 要記錄：</p>
<table>
  <thead>
      <tr>
          <th>Evidence</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CLI version</td>
          <td>Wrangler version、account / project</td>
      </tr>
      <tr>
          <td>Import log</td>
          <td>duration、file size、error</td>
      </tr>
      <tr>
          <td>Query result</td>
          <td>每個 query 的 row count / error</td>
      </tr>
      <tr>
          <td>Limit hit</td>
          <td>D1 limits 是否影響 seed 或 query</td>
      </tr>
      <tr>
          <td>Rollback</td>
          <td>刪除 preview DB 或重建 seed</td>
      </tr>
  </tbody>
</table>
<p>若 seed file 太大或某些 SQL 需要改寫，就把 gap 寫進 compatibility matrix，先保留 production migration 的審查邊界。</p>
<h2 id="import-to-turso-preview">Import to Turso Preview</h2>
<p>Import to Turso preview 的核心責任是驗證 remote database、client SDK 與 embedded replica 行為。以下是操作骨架，正式命令以 Turso docs 與 CLI version 為準。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Example shape only. Use your org, group, region and official Turso docs.</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">turso db create sqlite-edge-preview
</span></span><span class="line"><span class="ln">3</span><span class="cl">turso db shell sqlite-edge-preview &lt; seed.sql
</span></span><span class="line"><span class="ln">4</span><span class="cl">turso db shell sqlite-edge-preview <span class="s2">&#34;SELECT COUNT(*) FROM accounts;&#34;</span></span></span></code></pre></div><p>Turso preview evidence 要多記 replica freshness。若使用 embedded replica，測試流程要包含 bootstrap、sync、read query、write delegation 與 sync 後 read。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">embedded replica evidence:
</span></span><span class="line"><span class="ln">2</span><span class="cl">  bootstrap duration
</span></span><span class="line"><span class="ln">3</span><span class="cl">  first read latency
</span></span><span class="line"><span class="ln">4</span><span class="cl">  write path
</span></span><span class="line"><span class="ln">5</span><span class="cl">  sync command / interval
</span></span><span class="line"><span class="ln">6</span><span class="cl">  read freshness after write</span></span></code></pre></div><p>Freshness 是 product decision。若 query matrix 只測 remote primary，仍需要追加 embedded replica 的使用者體驗驗證。</p>
<h2 id="compatibility-matrix">Compatibility Matrix</h2>
<p>Compatibility matrix 的核心責任是把 local SQLite 與 edge target 的差異留下來。建議表格欄位如下：</p>
<table>
  <thead>
      <tr>
          <th>Query / operation</th>
          <th>Local SQLite</th>
          <th>D1 preview</th>
          <th>Turso preview</th>
          <th>Decision</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Balance list</td>
          <td>pass</td>
          <td>pass / diff</td>
          <td>pass / diff</td>
          <td>keep / rewrite</td>
      </tr>
      <tr>
          <td>Unique violation</td>
          <td>error class</td>
          <td>error class</td>
          <td>error class</td>
          <td>map error</td>
      </tr>
      <tr>
          <td>FK violation</td>
          <td>error class</td>
          <td>error class</td>
          <td>error class</td>
          <td>enable / validate</td>
      </tr>
      <tr>
          <td>Transaction rollback</td>
          <td>pass</td>
          <td>pass / diff</td>
          <td>pass / diff</td>
          <td>rewrite workflow</td>
      </tr>
      <tr>
          <td>Import seed</td>
          <td>pass</td>
          <td>duration / limit</td>
          <td>duration / limit</td>
          <td>split batch</td>
      </tr>
  </tbody>
</table>
<p>Decision 欄要寫具體下一步。<code>rewrite workflow</code> 代表 application adapter 要改；<code>split batch</code> 代表 migration runbook 要改；<code>map error</code> 代表 repository error classification 要改。</p>
<h2 id="latency-and-cost-sample">Latency and Cost Sample</h2>
<p>Latency and cost sample 的核心責任是避免只看功能相容。Edge SQLite migration 的收益常來自 region latency 或 managed operation，因此 preview 要量測主要使用者區域的 read / write latency。</p>
<p>最小量測：</p>
<ol>
<li>Local baseline latency。</li>
<li>Preview target read latency。</li>
<li>Preview target write latency。</li>
<li>Error rate / retry count。</li>
<li>Estimated request / storage / egress cost。</li>
</ol>
<p>Latency sample 要搭配 freshness。快速讀到舊資料和稍慢讀到最新資料是不同產品體驗；query matrix 要標註哪個 workflow 可以接受 stale read。</p>
<h2 id="rollback-route">Rollback Route</h2>
<p>Rollback route 的核心責任是保留 local SQLite 退路。Preview lab 完成後，要能刪除 preview database、保留 local seed、重跑 local app。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sqlite3 app.db <span class="s2">&#34;PRAGMA integrity_check;&#34;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sqlite3 app.db <span class="s2">&#34;SELECT COUNT(*) FROM accounts;&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">sqlite3 app.db <span class="s2">&#34;SELECT COUNT(*) FROM ledger_entries;&#34;</span></span></span></code></pre></div><p>正式 cutover 的 rollback 還要處理 target-only writes。Preview 階段應避免讓真實使用者寫入 target；若需要 shadow traffic，先用 read-only 或 synthetic write。</p>
<h2 id="completion-note">Completion Note</h2>
<p>Completion note 的核心責任是決定是否進入正式 migration。Lab 完成後應輸出四個 artifact：<code>seed.sql</code>、import log、compatibility matrix、rollback note。</p>
<p>進入正式 migration 的條件：</p>
<ol>
<li>Query matrix 主要 workflow 通過或已有 rewrite plan。</li>
<li>Platform limits 對資料量與 migration time 可接受。</li>
<li>Error mapping 已接到 repository adapter。</li>
<li>Freshness / latency 符合產品需求。</li>
<li>Export / rollback route 已演練。</li>
</ol>
<p>完成本篇後，回到 <a href="/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/" data-link-title="SQLite to D1 / Turso Migration" data-link-desc="SQLite 轉向 Cloudflare D1、Turso / libSQL 的 edge driver、compatibility audit、data movement 與 rollback">SQLite to D1 / Turso Migration</a> 補正式 phase plan。</p>
]]></content:encoded></item></channel></rss>