<?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>Turso on Tarragon</title><link>https://tarrragon.github.io/blog/tags/turso/</link><description>Recent content in Turso 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/turso/index.xml" rel="self" type="application/rss+xml"/><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 to D1 / Turso Migration</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/</link><pubDate>Thu, 21 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/sqlite/migrate-to-d1-turso/</guid><description>&lt;p>SQLite to D1 / Turso migration 的核心責任是把 local SQLite 轉成 edge / serverless / distributed SQLite-compatible product。這條路線的 driver 通常是 edge locality、Workers integration、managed operation、global read latency、embedded replica 或 serverless deployment workflow。&lt;/p>
&lt;p>本文的判讀錨點是：D1 / Turso migration 是 runtime boundary 變更。Local file 直連變成 platform binding、remote endpoint 或 embedded replica；因此 migration 要同時審查 SQL support、data movement、driver API、auth、latency、freshness、backup 與 vendor exit。&lt;/p>
&lt;h2 id="migration-drivers">Migration Drivers&lt;/h2>
&lt;p>Migration drivers 的核心責任是確認 edge SQLite 產品解決的是哪個服務壓力。D1 與 Turso / libSQL 都接近 SQLite experience，但它們的採用理由應寫成具體 workload。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Driver&lt;/th>
 &lt;th>適合產品&lt;/th>
 &lt;th>判讀訊號&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Workers integration&lt;/td>
 &lt;td>Cloudflare D1&lt;/td>
 &lt;td>App 已在 Workers、資料量小、query 清楚&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Serverless low ops&lt;/td>
 &lt;td>D1 / Turso&lt;/td>
 &lt;td>不想維護 host DB、可接受 platform limit&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Low-latency read&lt;/td>
 &lt;td>Turso / embedded replica&lt;/td>
 &lt;td>read-heavy、freshness window 明確&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Edge-local app&lt;/td>
 &lt;td>D1 / Turso&lt;/td>
 &lt;td>使用者分散、write rate 可控&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Portable SQLite base&lt;/td>
 &lt;td>Turso / libSQL&lt;/td>
 &lt;td>想保留 SQLite-like schema 與 local dev&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>D1 的 migration driver 要和 Cloudflare platform 綁定。若 app 已用 Workers routing、KV、Queues 或 Pages，D1 可以降低跨平台整合成本；若 app 不在 Cloudflare 生態，D1 的價值要用 latency、operation 與成本證明。&lt;/p>
&lt;p>Turso / libSQL 的 migration driver 要和 replica freshness 綁定。若使用者需要 local read speed，embedded replica 有價值；若產品要求每次讀都立即看到最新 global state，就要先設計 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-after-write/" data-link-title="Read-After-Write Consistency" data-link-desc="說明寫入後能否立即讀到該筆寫入的一致性保證">read-after-write&lt;/a> path。&lt;/p>
&lt;h2 id="compatibility-audit">Compatibility Audit&lt;/h2>
&lt;p>Compatibility audit 的核心責任是確認 local SQLite schema、query 與 migration workflow 可在 target product 上運作。官方文件要作為 limits 與 feature 的單一來源：D1 參考 &lt;a href="https://developers.cloudflare.com/d1/">Cloudflare D1 docs&lt;/a> 與 &lt;a href="https://developers.cloudflare.com/d1/platform/limits/">D1 limits&lt;/a>；Turso 參考 &lt;a href="https://docs.turso.tech/">Turso docs&lt;/a> 與 libSQL client reference。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>面向&lt;/th>
 &lt;th>審查問題&lt;/th>
 &lt;th>Evidence&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>SQL support&lt;/td>
 &lt;td>schema、trigger、index、JSON、FK&lt;/td>
 &lt;td>migration dry run、query suite&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Size / batch&lt;/td>
 &lt;td>import file、query duration、batch size&lt;/td>
 &lt;td>limit review、sample import&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Driver API&lt;/td>
 &lt;td>local file path 變成 binding / endpoint&lt;/td>
 &lt;td>repository adapter test&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Auth&lt;/td>
 &lt;td>token、binding、environment secret&lt;/td>
 &lt;td>staging deployment&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Transaction&lt;/td>
 &lt;td>request boundary、retry、write location&lt;/td>
 &lt;td>failure injection&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Backup&lt;/td>
 &lt;td>export、restore、retention&lt;/td>
 &lt;td>restore drill&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Compatibility audit 要以 production query 為單位。只跑 &lt;code>CREATE TABLE&lt;/code> 會漏掉最重要的差異；query suite 要包含 list page、pagination、unique violation、FK violation、transaction rollback、large batch 與 slow query。&lt;/p></description><content:encoded><![CDATA[<p>SQLite to D1 / Turso migration 的核心責任是把 local SQLite 轉成 edge / serverless / distributed SQLite-compatible product。這條路線的 driver 通常是 edge locality、Workers integration、managed operation、global read latency、embedded replica 或 serverless deployment workflow。</p>
<p>本文的判讀錨點是：D1 / Turso migration 是 runtime boundary 變更。Local file 直連變成 platform binding、remote endpoint 或 embedded replica；因此 migration 要同時審查 SQL support、data movement、driver API、auth、latency、freshness、backup 與 vendor exit。</p>
<h2 id="migration-drivers">Migration Drivers</h2>
<p>Migration drivers 的核心責任是確認 edge SQLite 產品解決的是哪個服務壓力。D1 與 Turso / libSQL 都接近 SQLite experience，但它們的採用理由應寫成具體 workload。</p>
<table>
  <thead>
      <tr>
          <th>Driver</th>
          <th>適合產品</th>
          <th>判讀訊號</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Workers integration</td>
          <td>Cloudflare D1</td>
          <td>App 已在 Workers、資料量小、query 清楚</td>
      </tr>
      <tr>
          <td>Serverless low ops</td>
          <td>D1 / Turso</td>
          <td>不想維護 host DB、可接受 platform limit</td>
      </tr>
      <tr>
          <td>Low-latency read</td>
          <td>Turso / embedded replica</td>
          <td>read-heavy、freshness window 明確</td>
      </tr>
      <tr>
          <td>Edge-local app</td>
          <td>D1 / Turso</td>
          <td>使用者分散、write rate 可控</td>
      </tr>
      <tr>
          <td>Portable SQLite base</td>
          <td>Turso / libSQL</td>
          <td>想保留 SQLite-like schema 與 local dev</td>
      </tr>
  </tbody>
</table>
<p>D1 的 migration driver 要和 Cloudflare platform 綁定。若 app 已用 Workers routing、KV、Queues 或 Pages，D1 可以降低跨平台整合成本；若 app 不在 Cloudflare 生態，D1 的價值要用 latency、operation 與成本證明。</p>
<p>Turso / libSQL 的 migration driver 要和 replica freshness 綁定。若使用者需要 local read speed，embedded replica 有價值；若產品要求每次讀都立即看到最新 global state，就要先設計 <a href="/blog/backend/knowledge-cards/read-after-write/" data-link-title="Read-After-Write Consistency" data-link-desc="說明寫入後能否立即讀到該筆寫入的一致性保證">read-after-write</a> path。</p>
<h2 id="compatibility-audit">Compatibility Audit</h2>
<p>Compatibility audit 的核心責任是確認 local SQLite schema、query 與 migration workflow 可在 target product 上運作。官方文件要作為 limits 與 feature 的單一來源：D1 參考 <a href="https://developers.cloudflare.com/d1/">Cloudflare D1 docs</a> 與 <a href="https://developers.cloudflare.com/d1/platform/limits/">D1 limits</a>；Turso 參考 <a href="https://docs.turso.tech/">Turso docs</a> 與 libSQL client reference。</p>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>審查問題</th>
          <th>Evidence</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SQL support</td>
          <td>schema、trigger、index、JSON、FK</td>
          <td>migration dry run、query suite</td>
      </tr>
      <tr>
          <td>Size / batch</td>
          <td>import file、query duration、batch size</td>
          <td>limit review、sample import</td>
      </tr>
      <tr>
          <td>Driver API</td>
          <td>local file path 變成 binding / endpoint</td>
          <td>repository adapter test</td>
      </tr>
      <tr>
          <td>Auth</td>
          <td>token、binding、environment secret</td>
          <td>staging deployment</td>
      </tr>
      <tr>
          <td>Transaction</td>
          <td>request boundary、retry、write location</td>
          <td>failure injection</td>
      </tr>
      <tr>
          <td>Backup</td>
          <td>export、restore、retention</td>
          <td>restore drill</td>
      </tr>
  </tbody>
</table>
<p>Compatibility audit 要以 production query 為單位。只跑 <code>CREATE TABLE</code> 會漏掉最重要的差異；query suite 要包含 list page、pagination、unique violation、FK violation、transaction rollback、large batch 與 slow query。</p>
<h2 id="data-movement">Data Movement</h2>
<p>Data movement 的核心責任是把 SQLite file 轉成 target platform 可接受的 seed。Local SQLite 可以先 export 成 SQL dump、CSV 或 platform CLI 支援的 import format，再進 target product。</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;.dump&#34;</span> &gt; seed.sql</span></span></code></pre></div><p>這段命令只是 seed 起點。正式流程要處理 schema ordering、unsupported SQL、large transaction、batch split、sensitive data masking、import duration、row count 與 checksum。</p>
<p>D1 migration 要把 Wrangler / platform workflow 納入 runbook。Cloudflare D1 的 limits 文件列出 import 與 query 限制；大型資料變更應切 batch，並在 preview / staging database 跑完整 dry run。</p>
<p>Turso migration 要把 remote database 與 embedded replica 分開驗證。Seed 完 remote primary 後，要測 local embedded replica 的 bootstrap、sync、read freshness、write delegation 與 offline behavior。</p>
<h2 id="application-change">Application Change</h2>
<p>Application change 的核心責任是把 database access 從 file path 改成可替換 adapter。Local SQLite 常用 file path 與 process-local connection；D1 / Turso 會加入 binding、endpoint、token、client SDK、network failure 與 platform runtime。</p>
<table>
  <thead>
      <tr>
          <th>改動層</th>
          <th>Local SQLite</th>
          <th>D1 / Turso route</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Connection</td>
          <td>file path</td>
          <td>Workers binding、HTTP / libSQL endpoint</td>
      </tr>
      <tr>
          <td>Auth</td>
          <td>filesystem permission</td>
          <td>platform secret、token、binding</td>
      </tr>
      <tr>
          <td>Error model</td>
          <td>SQLite error code</td>
          <td>SDK / platform error + SQLite-like error</td>
      </tr>
      <tr>
          <td>Retry</td>
          <td>local busy / lock retry</td>
          <td>network retry、idempotency、timeout</td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>app log + file metric</td>
          <td>app log + platform metric</td>
      </tr>
  </tbody>
</table>
<p>Repository adapter 要承擔 driver 差異。Domain layer 應看到穩定的 repository contract，例如 duplicate key、stale read、temporary unavailable、retryable write；底層才處理 D1 binding 或 libSQL client。</p>
<p>Idempotency 是 edge migration 的關鍵。Write request 進入 network / serverless runtime 後，retry 可能在 client、platform 或 application 層發生；每個 critical write 都應有 idempotency key 或 natural unique key。</p>
<h2 id="evidence">Evidence</h2>
<p>Evidence 的核心責任是證明 edge migration 帶來的收益大於新風險。D1 / Turso 的成功要同時看功能可用、region latency、freshness、error rate、cost、migration time 與 exit route。</p>
<table>
  <thead>
      <tr>
          <th>Evidence</th>
          <th>最小驗證方式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Latency by region</td>
          <td>從主要 user region 跑 read/write test</td>
      </tr>
      <tr>
          <td>Freshness</td>
          <td>write 後在 replica / edge read 檢查</td>
      </tr>
      <tr>
          <td>Migration repeatability</td>
          <td>staging database 從空庫重跑 seed</td>
      </tr>
      <tr>
          <td>Error mapping</td>
          <td>duplicate、constraint、timeout、auth</td>
      </tr>
      <tr>
          <td>Cost</td>
          <td>request、storage、egress、operation</td>
      </tr>
      <tr>
          <td>Exit route</td>
          <td>export file + restore to local SQLite</td>
      </tr>
  </tbody>
</table>
<p>Freshness evidence 要用產品語言寫。若 UI 可以顯示「同步中」，freshness window 可被使用者理解；若是付款、庫存、權限決策，讀舊資料會直接造成業務錯誤，這類 workflow 要走 primary read 或 server SQL。</p>
<p>Exit route 要被演練。Edge product 的 adoption cost 低，exit cost 會出現在 driver API、migration workflow、platform binding 與 data export；至少要能把 staging data export 回 SQLite file 並通過 smoke test。</p>
<h2 id="rollback">Rollback</h2>
<p>Rollback 的核心責任是保留 local SQLite snapshot 與 read-only fallback。Edge migration 若在 cutover 後遇到 auth、latency、limit 或 query error，團隊要能快速回到上一個可用資料狀態。</p>
<table>
  <thead>
      <tr>
          <th>Rollback 觸發</th>
          <th>回退策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Import / migration 失敗</td>
          <td>清空 target、修 migration、重跑 seed</td>
      </tr>
      <tr>
          <td>Query error spike</td>
          <td>切回 local SQLite / previous endpoint</td>
      </tr>
      <tr>
          <td>Freshness issue</td>
          <td>critical read 改 primary path</td>
      </tr>
      <tr>
          <td>Cost / limit spike</td>
          <td>降低 traffic、batch migration、重評估</td>
      </tr>
      <tr>
          <td>Vendor incident</td>
          <td>read-only mode、fallback endpoint</td>
      </tr>
  </tbody>
</table>
<p>Local snapshot 要保存到 cutover 後的觀察窗口結束。若 cutover 期間已有 target-only writes，要設計回放或 reconciliation；高風險 workflow 可以先進 read-only cutover，再逐步開寫。</p>
<h2 id="decision-route">Decision Route</h2>
<p>Decision route 的核心責任是把 edge migration 和 server DB migration 分開。D1 / Turso 適合 edge runtime 與 SQLite-like workflow；當需求轉向 central audit、server role、high-write OLTP 或 distributed transaction，應改走 PostgreSQL / CockroachDB / Spanner。</p>
<table>
  <thead>
      <tr>
          <th>需求</th>
          <th>路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Workers app + small relational data</td>
          <td>D1</td>
      </tr>
      <tr>
          <td>Read-heavy app + local replica value</td>
          <td>Turso / libSQL</td>
      </tr>
      <tr>
          <td>Backup / restore 是主要問題</td>
          <td><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 + permission + audit</td>
          <td><a href="/blog/backend/01-database/vendors/sqlite/migrate-to-postgresql/" data-link-title="SQLite to PostgreSQL Migration" data-link-desc="SQLite 升級到 PostgreSQL 的 driver、schema diff、data copy、dual run、cutover、rollback 與 cleanup">SQLite to PostgreSQL</a></td>
      </tr>
      <tr>
          <td>Global write transaction</td>
          <td><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></td>
      </tr>
  </tbody>
</table>
<h2 id="下一步路由">下一步路由</h2>
<p>SQLite to D1 / Turso migration 完成後，先讀 <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> 釐清 product boundary；再用 <a href="/blog/backend/01-database/vendors/sqlite/sql-dialect-index-limits/" data-link-title="SQLite SQL Dialect and Index Limits" data-link-desc="SQLite type affinity、NULL / date handling、constraint、index、query planner 與 PostgreSQL / MySQL 差異">SQL dialect and index limits</a> 做 compatibility audit；需要操作演練時讀 <a href="/blog/backend/01-database/vendors/sqlite/hands-on/d1-turso-preview-lab/" data-link-title="SQLite D1 / Turso Preview Lab" data-link-desc="SQLite local DB 匯出到 Cloudflare D1 或 Turso preview environment 的 compatibility、latency 與 rollback 操作說明">D1 / Turso preview lab</a>。</p>
]]></content:encoded></item></channel></rss>