<?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>服務上線的業界常識地基 on Tarragon</title><link>https://tarrragon.github.io/blog/going-live/</link><description>Recent content in 服務上線的業界常識地基 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 06 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/going-live/index.xml" rel="self" type="application/rss+xml"/><item><title>部署到底是什麼</title><link>https://tarrragon.github.io/blog/going-live/what-is-deploy/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/what-is-deploy/</guid><description>&lt;p>部署（deploy）就是「讓你的程式跑在一台&lt;strong>永遠開著、且網際網路連得到&lt;/strong>的電腦上」，而不是跑在你會關機、會睡眠、只有你自己連得到的筆電上。你在本機 &lt;code>npm start&lt;/code> / &lt;code>php -S&lt;/code> 跑起來，跟服務「上線」之間，變的是這台電腦的四個性質，而不只是那行指令。&lt;/p>
&lt;h2 id="從本機跑到上線變的是這四件事">從本機跑到上線，變的是這四件事&lt;/h2>
&lt;p>同樣一份 code，放到線上要滿足四個本機不需要的條件：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>機器永遠開著&lt;/strong>：你的筆電會關、會睡、會斷網。線上要一台 24 小時開著的電腦（雲主機、VPS、或平台幫你顧的機器），你闔上筆電服務也不能停。&lt;/li>
&lt;li>&lt;strong>網際網路連得到&lt;/strong>：本機是 &lt;code>localhost&lt;/code>（只有你這台連得到）。線上要一個&lt;strong>公開位址&lt;/strong>——一個公網 IP，通常再掛一個域名（&lt;code>example.com&lt;/code>）指過去，別人才連得到。&lt;/li>
&lt;li>&lt;strong>沒人顧也要活著&lt;/strong>：本機是你手動 &lt;code>start&lt;/code>、崩了你再手動重跑。線上要能&lt;strong>開機自動啟動、崩潰自動重啟&lt;/strong>——半夜掛了不能等你醒來。&lt;/li>
&lt;li>&lt;strong>面對的是真實流量與環境&lt;/strong>：線上同時被很多人打（並發）、被掃描攻擊（安全）、而且設定跟你本機不同（資料庫位址、密鑰、環境變數都不一樣）。&lt;/li>
&lt;/ul>
&lt;p>「部署」這個動作，本質就是把 code 搬到一台滿足這四點的機器上、並讓它以正確的設定跑起來。&lt;/p>
&lt;h2 id="一次部署實際包含哪些步驟">一次部署實際包含哪些步驟&lt;/h2>
&lt;p>把上面四點拆成動作，一次最基本的部署大致是：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>準備一台線上機器&lt;/strong>（或一個幫你跑 code 的平台）——這是「&lt;a href="https://tarrragon.github.io/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態&lt;/a>」要選的。&lt;/li>
&lt;li>&lt;strong>把 code 送上去&lt;/strong>——git pull、或打包成 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container image&lt;/a> 推到 &lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">registry&lt;/a>（存放 image 的倉庫）再拉下來。&lt;/li>
&lt;li>&lt;strong>裝好依賴、帶上正確設定&lt;/strong>——線上的 DB 位址、密鑰用&lt;a href="https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">環境變數&lt;/a>注入，不是寫死在 code 裡。&lt;/li>
&lt;li>&lt;strong>讓它開機自動起、崩潰自動重啟&lt;/strong>——用 systemd、或平台/&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container-per-service/" data-link-title="Container-per-Service（一容器一職責）" data-link-desc="第一次發現一個 web app 要開好幾個 container、不懂為什麼不塞一個大 container、或不確定什麼該獨立成一個 container 時回來讀 — 一容器一職責的理由與邊界">container 編排器&lt;/a>管生命週期。&lt;/li>
&lt;li>&lt;strong>讓外面連得到&lt;/strong>——設&lt;a href="https://tarrragon.github.io/blog/going-live/domain-and-https/" data-link-title="域名與 HTTPS 怎麼接上" data-link-desc="服務跑在一個 IP 上了、但不知道買的域名怎麼指過去、網址前面的鎖頭（HTTPS）憑證從哪來時回來讀 — 域名解析與 TLS 的最小認識">域名與 HTTPS&lt;/a>、開對的 port。&lt;/li>
&lt;/ol>
&lt;p>有資料庫的服務還多一步：第一次上線要跑一次 &lt;strong>schema 初始化 / migration&lt;/strong> 把資料表建起來——步驟 3 帶的是「DB 位址」，不等於「DB 裡有表」，漏了這步就是 code 上去了、一連 DB 就爆的典型翻車（migration 屬「一次性 admin process」，每次改資料表結構都要跑）。&lt;/p>
&lt;p>常見的誤解是把「部署」等同步驟 2 的「把 code 傳上去」，但真正讓服務「活著且可用」的是其餘幾步。&lt;/p>
&lt;h2 id="判讀你其實已經在部署了">判讀：你其實已經在部署了&lt;/h2>
&lt;p>如果你用過 Heroku / Vercel / Render 這種平台按一下就上線，你已經部署過了——只是平台把上面 1、4、5 全包了，你只做了 2、3，也就是&lt;strong>平台幫你扛掉大部分部署工作&lt;/strong>（這正是&lt;a href="https://tarrragon.github.io/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態光譜&lt;/a>的一端）。理解「部署包含哪五步」，是為了在平台包不住、要自己顧機器時，知道每一步在做什麼。&lt;/p>
&lt;h2 id="邊界與下一步">邊界與下一步&lt;/h2>
&lt;p>這篇講的是「單次把服務弄上線」。真實服務會反覆部署新版本，這時要處理「更新時怎麼不中斷服務」——舊版還在服務、新版怎麼接手、出錯怎麼退回。那是進階的部署策略，見 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/deployment-rollout-drain-rollback/" data-link-title="5.8 Deployment Rollout with Drain and Rollback（實作示範）" data-link-desc="以 checkout service 示範部署切換如何交付 canary evidence、drain signal、release gate 與 incident decision log。">Backend 部署 rollout / drain / rollback&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/ci/" data-link-title="CI/CD 教學" data-link-desc="整理 CI/CD 的驗證、建置、發布 gate 與不同部署場域的流程差異，讓每次變更都能被穩定驗證與交付">CI/CD&lt;/a>。&lt;/p>
&lt;p>先搞懂「我的 code 到底該跑在哪」，往下讀 &lt;a href="https://tarrragon.github.io/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態光譜&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>部署（deploy）就是「讓你的程式跑在一台<strong>永遠開著、且網際網路連得到</strong>的電腦上」，而不是跑在你會關機、會睡眠、只有你自己連得到的筆電上。你在本機 <code>npm start</code> / <code>php -S</code> 跑起來，跟服務「上線」之間，變的是這台電腦的四個性質，而不只是那行指令。</p>
<h2 id="從本機跑到上線變的是這四件事">從本機跑到上線，變的是這四件事</h2>
<p>同樣一份 code，放到線上要滿足四個本機不需要的條件：</p>
<ul>
<li><strong>機器永遠開著</strong>：你的筆電會關、會睡、會斷網。線上要一台 24 小時開著的電腦（雲主機、VPS、或平台幫你顧的機器），你闔上筆電服務也不能停。</li>
<li><strong>網際網路連得到</strong>：本機是 <code>localhost</code>（只有你這台連得到）。線上要一個<strong>公開位址</strong>——一個公網 IP，通常再掛一個域名（<code>example.com</code>）指過去，別人才連得到。</li>
<li><strong>沒人顧也要活著</strong>：本機是你手動 <code>start</code>、崩了你再手動重跑。線上要能<strong>開機自動啟動、崩潰自動重啟</strong>——半夜掛了不能等你醒來。</li>
<li><strong>面對的是真實流量與環境</strong>：線上同時被很多人打（並發）、被掃描攻擊（安全）、而且設定跟你本機不同（資料庫位址、密鑰、環境變數都不一樣）。</li>
</ul>
<p>「部署」這個動作，本質就是把 code 搬到一台滿足這四點的機器上、並讓它以正確的設定跑起來。</p>
<h2 id="一次部署實際包含哪些步驟">一次部署實際包含哪些步驟</h2>
<p>把上面四點拆成動作，一次最基本的部署大致是：</p>
<ol>
<li><strong>準備一台線上機器</strong>（或一個幫你跑 code 的平台）——這是「<a href="/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態</a>」要選的。</li>
<li><strong>把 code 送上去</strong>——git pull、或打包成 <a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container image</a> 推到 <a href="/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">registry</a>（存放 image 的倉庫）再拉下來。</li>
<li><strong>裝好依賴、帶上正確設定</strong>——線上的 DB 位址、密鑰用<a href="/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">環境變數</a>注入，不是寫死在 code 裡。</li>
<li><strong>讓它開機自動起、崩潰自動重啟</strong>——用 systemd、或平台/<a href="/blog/backend/knowledge-cards/container-per-service/" data-link-title="Container-per-Service（一容器一職責）" data-link-desc="第一次發現一個 web app 要開好幾個 container、不懂為什麼不塞一個大 container、或不確定什麼該獨立成一個 container 時回來讀 — 一容器一職責的理由與邊界">container 編排器</a>管生命週期。</li>
<li><strong>讓外面連得到</strong>——設<a href="/blog/going-live/domain-and-https/" data-link-title="域名與 HTTPS 怎麼接上" data-link-desc="服務跑在一個 IP 上了、但不知道買的域名怎麼指過去、網址前面的鎖頭（HTTPS）憑證從哪來時回來讀 — 域名解析與 TLS 的最小認識">域名與 HTTPS</a>、開對的 port。</li>
</ol>
<p>有資料庫的服務還多一步：第一次上線要跑一次 <strong>schema 初始化 / migration</strong> 把資料表建起來——步驟 3 帶的是「DB 位址」，不等於「DB 裡有表」，漏了這步就是 code 上去了、一連 DB 就爆的典型翻車（migration 屬「一次性 admin process」，每次改資料表結構都要跑）。</p>
<p>常見的誤解是把「部署」等同步驟 2 的「把 code 傳上去」，但真正讓服務「活著且可用」的是其餘幾步。</p>
<h2 id="判讀你其實已經在部署了">判讀：你其實已經在部署了</h2>
<p>如果你用過 Heroku / Vercel / Render 這種平台按一下就上線，你已經部署過了——只是平台把上面 1、4、5 全包了，你只做了 2、3，也就是<strong>平台幫你扛掉大部分部署工作</strong>（這正是<a href="/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態光譜</a>的一端）。理解「部署包含哪五步」，是為了在平台包不住、要自己顧機器時，知道每一步在做什麼。</p>
<h2 id="邊界與下一步">邊界與下一步</h2>
<p>這篇講的是「單次把服務弄上線」。真實服務會反覆部署新版本，這時要處理「更新時怎麼不中斷服務」——舊版還在服務、新版怎麼接手、出錯怎麼退回。那是進階的部署策略，見 <a href="/blog/backend/05-deployment-platform/deployment-rollout-drain-rollback/" data-link-title="5.8 Deployment Rollout with Drain and Rollback（實作示範）" data-link-desc="以 checkout service 示範部署切換如何交付 canary evidence、drain signal、release gate 與 incident decision log。">Backend 部署 rollout / drain / rollback</a> 與 <a href="/blog/ci/" data-link-title="CI/CD 教學" data-link-desc="整理 CI/CD 的驗證、建置、發布 gate 與不同部署場域的流程差異，讓每次變更都能被穩定驗證與交付">CI/CD</a>。</p>
<p>先搞懂「我的 code 到底該跑在哪」，往下讀 <a href="/blog/going-live/hosting-spectrum/" data-link-title="主機形態光譜" data-link-desc="第一次要選服務跑在哪、被 VPS / IaaS / PaaS / serverless 這些詞搞混、不知道差在哪時回來讀 — 主機形態是一道「你管多少」的光譜">主機形態光譜</a>。</p>
]]></content:encoded></item><item><title>主機形態光譜</title><link>https://tarrragon.github.io/blog/going-live/hosting-spectrum/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/hosting-spectrum/</guid><description>&lt;p>主機形態是一道光譜，一個軸就講完：&lt;strong>你管多少、平台管多少。&lt;/strong> 從「租一台空機器什麼都自己裝」到「只丟一段函式其餘全平台顧」，中間每一格都是拿「控制權」換「維運工作」。搞懂這個軸，那些名詞（VPS / IaaS / PaaS / serverless）就各就各位。&lt;/p>
&lt;h2 id="一道光譜從自己管到平台管">一道光譜，從自己管到平台管&lt;/h2>
&lt;p>由左（你管最多）到右（平台管最多）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">你管越多 ←───────────────────────────────────────→ 平台管越多
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">裸機/VPS(IaaS) PaaS Serverless 全託管 SaaS
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">給你一台機器 給你跑 code 的環境 給你跑函式的環境 你只用、不部署
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">OS/runtime/DB platform 管佈署 平台管一切、可縮到零 供應商全包
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">/web server 全自己 你只給 code&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;strong>VPS / IaaS&lt;/strong>（DigitalOcean Droplet、AWS EC2、Hetzner）：平台給你一台（虛擬）機器，OS 以上全你自己裝——runtime（語言執行環境，如 Node/PHP）、web server、DB、開機自動啟動、更新。控制權最大，維運工作也最多。&lt;/li>
&lt;li>&lt;strong>PaaS&lt;/strong>（Heroku、Render、Railway、Cloud Run、App Runner）：你把 code（或 container image）交給平台，平台管佈署、擴縮、TLS（HTTPS 憑證）、健康檢查。你不碰機器。控制權少一些，省掉大量維運。&lt;/li>
&lt;li>&lt;strong>Serverless / FaaS&lt;/strong>（AWS Lambda、Cloud Functions、Cloudflare Workers）：你交的是一段函式，平台按請求觸發、沒流量時縮到零、不收錢（指函式本身；後面的 DB、儲存、API gateway 仍照計費）。最省維運，但要遷就它的執行模型（&lt;a href="https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">無狀態&lt;/a>、有執行時間上限、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">冷啟動&lt;/a>——閒置後第一個請求要等它重新起來），本地開發與除錯也比較麻煩。&lt;/li>
&lt;li>&lt;strong>BaaS（backend-as-a-service）&lt;/strong>（Firebase、Supabase）：連資料庫、認證、後端邏輯層都幫你包，你主要寫前端 + 設定。部署這件事幾乎消失。（再往外就是現成的 SaaS 成品軟體——你只用、連 code 都不寫，那已經不在「部署」的範圍內。）&lt;/li>
&lt;/ul>
&lt;h2 id="怎麼在光譜上選位置">怎麼在光譜上選位置&lt;/h2>
&lt;p>選位置看的是「哪個匹配你現在的處境」，沒有絕對最好的一格：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>想學底層、要完全控制、或有特殊系統依賴&lt;/strong> → 偏左（VPS）。你會親手做完&lt;a href="https://tarrragon.github.io/blog/going-live/what-is-deploy/" data-link-title="部署到底是什麼" data-link-desc="第一次要把服務放上線、不確定「部署」到底在做什麼、跟在本機跑 npm start 差在哪時回來讀 — 上線這個動作的本質">部署的五步&lt;/a>，學最多，但半夜掛了是你的事。&lt;/li>
&lt;li>&lt;strong>要快速上線、團隊時間比機器費用值錢、不想當維運&lt;/strong> → 偏中（PaaS）。丟 code 就上線，平台顧機器。多數小團隊 / 早期產品的甜蜜點；代價是 vendor lock-in、規模長大後費用可能陡升。&lt;/li>
&lt;li>&lt;strong>流量尖峰型或很低、想離峰不花錢&lt;/strong> → 考慮右（serverless）。但要接受它的執行模型限制。&lt;/li>
&lt;/ul>
&lt;p>注意「省錢」不是單調對應這條軸——它是另一條軸。低流量時 serverless 離峰縮到零反而可能最省；高流量穩定跑時 VPS 的固定成本又划算。所以選位置先看「控制權 vs 維運」，成本另外算，別把「省錢」綁死在某一端。&lt;/p>
&lt;p>同一個服務的不同部分可以落在不同位置：app 用 PaaS、DB 用&lt;a href="https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">全託管&lt;/a>、靜態檔案丟 CDN——這很常見、也常是最省事的組合。&lt;/p>
&lt;h2 id="邊界與下一步">邊界與下一步&lt;/h2>
&lt;p>主機選好、code 有地方跑之後，接著要讓外面連得到——見 &lt;a href="https://tarrragon.github.io/blog/going-live/domain-and-https/" data-link-title="域名與 HTTPS 怎麼接上" data-link-desc="服務跑在一個 IP 上了、但不知道買的域名怎麼指過去、網址前面的鎖頭（HTTPS）憑證從哪來時回來讀 — 域名解析與 TLS 的最小認識">域名與 HTTPS 怎麼接上&lt;/a>。&lt;/p>
&lt;p>延伸：「app 跑在哪種形態的主機」跟「某個具體元件（DB）要自己顧還是託管」是同一個軸的兩種切法，後者見 &lt;a href="https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架還是託管：以資料庫為例&lt;/a>；「值不值得自建」的商業選型角度見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">Backend 交付形態選型&lt;/a>；VPS 這一端往上長成「用 IaC 管整套雲端地基」，見 &lt;a href="https://tarrragon.github.io/blog/infra/" data-link-title="Infra 基礎設施建置指南" data-link-desc="從零循序漸進把雲端基礎設施做起來 — IaC、身分憑證、網路地基、環境分離、核心服務、可觀測性、自動化 review 與治理習慣，含怎麼在組織內推動">Infra 指南&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>主機形態是一道光譜，一個軸就講完：<strong>你管多少、平台管多少。</strong> 從「租一台空機器什麼都自己裝」到「只丟一段函式其餘全平台顧」，中間每一格都是拿「控制權」換「維運工作」。搞懂這個軸，那些名詞（VPS / IaaS / PaaS / serverless）就各就各位。</p>
<h2 id="一道光譜從自己管到平台管">一道光譜，從自己管到平台管</h2>
<p>由左（你管最多）到右（平台管最多）：</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">你管越多 ←───────────────────────────────────────→ 平台管越多
</span></span><span class="line"><span class="ln">2</span><span class="cl">裸機/VPS(IaaS)      PaaS              Serverless        全託管 SaaS
</span></span><span class="line"><span class="ln">3</span><span class="cl">給你一台機器        給你跑 code 的環境  給你跑函式的環境    你只用、不部署
</span></span><span class="line"><span class="ln">4</span><span class="cl">OS/runtime/DB       platform 管佈署    平台管一切、可縮到零 供應商全包
</span></span><span class="line"><span class="ln">5</span><span class="cl">/web server 全自己  你只給 code</span></span></code></pre></div><ul>
<li><strong>VPS / IaaS</strong>（DigitalOcean Droplet、AWS EC2、Hetzner）：平台給你一台（虛擬）機器，OS 以上全你自己裝——runtime（語言執行環境，如 Node/PHP）、web server、DB、開機自動啟動、更新。控制權最大，維運工作也最多。</li>
<li><strong>PaaS</strong>（Heroku、Render、Railway、Cloud Run、App Runner）：你把 code（或 container image）交給平台，平台管佈署、擴縮、TLS（HTTPS 憑證）、健康檢查。你不碰機器。控制權少一些，省掉大量維運。</li>
<li><strong>Serverless / FaaS</strong>（AWS Lambda、Cloud Functions、Cloudflare Workers）：你交的是一段函式，平台按請求觸發、沒流量時縮到零、不收錢（指函式本身；後面的 DB、儲存、API gateway 仍照計費）。最省維運，但要遷就它的執行模型（<a href="/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">無狀態</a>、有執行時間上限、<a href="/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">冷啟動</a>——閒置後第一個請求要等它重新起來），本地開發與除錯也比較麻煩。</li>
<li><strong>BaaS（backend-as-a-service）</strong>（Firebase、Supabase）：連資料庫、認證、後端邏輯層都幫你包，你主要寫前端 + 設定。部署這件事幾乎消失。（再往外就是現成的 SaaS 成品軟體——你只用、連 code 都不寫，那已經不在「部署」的範圍內。）</li>
</ul>
<h2 id="怎麼在光譜上選位置">怎麼在光譜上選位置</h2>
<p>選位置看的是「哪個匹配你現在的處境」，沒有絕對最好的一格：</p>
<ul>
<li><strong>想學底層、要完全控制、或有特殊系統依賴</strong> → 偏左（VPS）。你會親手做完<a href="/blog/going-live/what-is-deploy/" data-link-title="部署到底是什麼" data-link-desc="第一次要把服務放上線、不確定「部署」到底在做什麼、跟在本機跑 npm start 差在哪時回來讀 — 上線這個動作的本質">部署的五步</a>，學最多，但半夜掛了是你的事。</li>
<li><strong>要快速上線、團隊時間比機器費用值錢、不想當維運</strong> → 偏中（PaaS）。丟 code 就上線，平台顧機器。多數小團隊 / 早期產品的甜蜜點；代價是 vendor lock-in、規模長大後費用可能陡升。</li>
<li><strong>流量尖峰型或很低、想離峰不花錢</strong> → 考慮右（serverless）。但要接受它的執行模型限制。</li>
</ul>
<p>注意「省錢」不是單調對應這條軸——它是另一條軸。低流量時 serverless 離峰縮到零反而可能最省；高流量穩定跑時 VPS 的固定成本又划算。所以選位置先看「控制權 vs 維運」，成本另外算，別把「省錢」綁死在某一端。</p>
<p>同一個服務的不同部分可以落在不同位置：app 用 PaaS、DB 用<a href="/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">全託管</a>、靜態檔案丟 CDN——這很常見、也常是最省事的組合。</p>
<h2 id="邊界與下一步">邊界與下一步</h2>
<p>主機選好、code 有地方跑之後，接著要讓外面連得到——見 <a href="/blog/going-live/domain-and-https/" data-link-title="域名與 HTTPS 怎麼接上" data-link-desc="服務跑在一個 IP 上了、但不知道買的域名怎麼指過去、網址前面的鎖頭（HTTPS）憑證從哪來時回來讀 — 域名解析與 TLS 的最小認識">域名與 HTTPS 怎麼接上</a>。</p>
<p>延伸：「app 跑在哪種形態的主機」跟「某個具體元件（DB）要自己顧還是託管」是同一個軸的兩種切法，後者見 <a href="/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架還是託管：以資料庫為例</a>；「值不值得自建」的商業選型角度見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">Backend 交付形態選型</a>；VPS 這一端往上長成「用 IaC 管整套雲端地基」，見 <a href="/blog/infra/" data-link-title="Infra 基礎設施建置指南" data-link-desc="從零循序漸進把雲端基礎設施做起來 — IaC、身分憑證、網路地基、環境分離、核心服務、可觀測性、自動化 review 與治理習慣，含怎麼在組織內推動">Infra 指南</a>。</p>
]]></content:encoded></item><item><title>域名與 HTTPS 怎麼接上</title><link>https://tarrragon.github.io/blog/going-live/domain-and-https/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/domain-and-https/</guid><description>&lt;p>你的服務跑在一台有公網 IP 的機器上之後，還差兩件事才「像個正常網站」：一是讓 &lt;code>example.com&lt;/code> 指到那個 IP（DNS），二是讓網址是 &lt;code>https://&lt;/code> 而不是 &lt;code>http://&lt;/code>（TLS 憑證）。這兩件都是每個上線服務的標配，但沒人明講時最容易卡住。&lt;/p>
&lt;h2 id="域名怎麼指到伺服器一筆-dns-紀錄">域名怎麼指到伺服器：一筆 DNS 紀錄&lt;/h2>
&lt;p>域名系統（DNS）是「把人記得住的名字翻成機器用的 IP」的電話簿。你在網域註冊商買下 &lt;code>example.com&lt;/code> 後，到它（或你用的 DNS 服務）的管理介面，加一筆 &lt;strong>A record&lt;/strong>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">類型 名稱 值（指向）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">A example.com 203.0.113.10 ← 你伺服器的公網 IP
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">A www 203.0.113.10&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A record 就是「這個名字 → 這個 IPv4」。加完後，全世界查 &lt;code>example.com&lt;/code> 會拿到你的 IP、連過來。幾個常見卡點：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>改了要等生效&lt;/strong>：DNS 有快取（TTL），改動可能幾分鐘到幾小時才全球生效，不是即時。&lt;/li>
&lt;li>&lt;strong>A vs CNAME&lt;/strong>：A 指向 IP；CNAME 指向「另一個域名」（常用在指到 PaaS 給你的網址，如 &lt;code>myapp.onrender.com&lt;/code>）。用 PaaS 時多半是設 CNAME——但裸網域 &lt;code>example.com&lt;/code>（apex）依 DNS 規範不能掛 CNAME，只能用 A、或供應商的 ALIAS/flattening，子網域（&lt;code>www&lt;/code>）才能 CNAME。這是 PaaS + 裸網域第一次上線的高頻卡點。&lt;/li>
&lt;li>&lt;strong>域名 ≠ 伺服器&lt;/strong>：買域名跟租主機是兩件事、常在不同供應商。域名只是指標，指向哪台機器由 A/CNAME 決定。&lt;/li>
&lt;/ul>
&lt;p>DNS 各紀錄類型的細節見 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/dns/" data-link-title="DNS" data-link-desc="Domain Name System — 把域名轉成 IP 位址的系統，以及 A record、CNAME、NS、TTL 的角色">Infra DNS 卡&lt;/a>。&lt;/p>
&lt;h2 id="https-的鎖頭從哪來tls-憑證">HTTPS 的鎖頭從哪來：TLS 憑證&lt;/h2>
&lt;p>&lt;code>https://&lt;/code> 前面那個鎖頭代表兩件事：&lt;strong>連線被加密&lt;/strong>（別人竊聽不到內容）、以及&lt;strong>對方身分被驗證&lt;/strong>（你連的真的是 &lt;code>example.com&lt;/code>、不是假冒的）。做到這兩點靠的是 &lt;strong>TLS 憑證&lt;/strong>——一份由受信任的憑證頒發機構（CA）簽發、證明「這個域名是這台伺服器的」的檔案。&lt;/p>
&lt;p>瀏覽器內建信任一批 CA。伺服器出示 CA 簽的憑證，瀏覽器驗章通過，鎖頭就亮、連線加密。憑證怎麼運作、CA 信任鏈的細節見 &lt;a href="https://tarrragon.github.io/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">Infra SSL/TLS 卡&lt;/a>。&lt;/p>
&lt;h2 id="憑證怎麼拿lets-encrypt-讓它免費又自動">憑證怎麼拿：Let&amp;rsquo;s Encrypt 讓它免費又自動&lt;/h2>
&lt;p>以前憑證要花錢買，現在 &lt;strong>Let&amp;rsquo;s Encrypt&lt;/strong> 這個免費 CA 讓它變成一行指令。它用 ACME 協議自動驗證「你確實控制這個域名」（通常是讓它連你的 server 或設一筆 DNS 紀錄），驗過就簽發，且能自動續期（憑證有 90 天效期）。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>自己顧機器（VPS）&lt;/strong>：用 &lt;code>certbot&lt;/code> 之類的工具，指令大致是 &lt;code>certbot --nginx -d example.com&lt;/code>——它自動取得憑證、改好 nginx 設定、排程續期。&lt;/li>
&lt;li>&lt;strong>用 PaaS&lt;/strong>：平台通常自動幫你上憑證，你只要把域名指過去（設 CNAME）就有 HTTPS，完全不碰 certbot。&lt;/li>
&lt;/ul>
&lt;h2 id="tls-在哪裡終結">TLS 在哪裡「終結」&lt;/h2>
&lt;p>加解密這件事通常由 app 前面的一層代勞——nginx、負載平衡器、或 CDN 負責「TLS termination」：對外收 HTTPS、解密後用普通 HTTP 轉給後面的 app。所以你 app 本身常常只講 HTTP，HTTPS 是前面那層加上去的。反向代理 / LB 承擔這類職責的細節見 &lt;a href="https://tarrragon.github.io/blog/operations/01-load-balancing/reverse-proxy-responsibilities/" data-link-title="反向代理的職責" data-link-desc="釐清反向代理在單一入口後面承擔哪些職責、TLS 終止與路由怎麼設計、以及一條請求路徑上的 timeout 為什麼要由外到內遞減時回來讀">運行期維運 反向代理職責&lt;/a>。&lt;/p>
&lt;h2 id="下一步">下一步&lt;/h2>
&lt;p>域名跟 HTTPS 接上，服務就「對外像個正常網站」了。接著是讓服務本身好部署、好搬家——見 &lt;a href="https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">十二要素基線&lt;/a>。用 IaC 把 DNS 與憑證納管（Route53 + ACM）的進階做法見 &lt;a href="https://tarrragon.github.io/blog/infra/05-core-services/" data-link-title="模組五：核心服務上 IaC" data-link-desc="資料庫、運算、儲存、load balancer 怎麼寫進基礎設施程式碼，以及上線順序">Infra 核心服務&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>你的服務跑在一台有公網 IP 的機器上之後，還差兩件事才「像個正常網站」：一是讓 <code>example.com</code> 指到那個 IP（DNS），二是讓網址是 <code>https://</code> 而不是 <code>http://</code>（TLS 憑證）。這兩件都是每個上線服務的標配，但沒人明講時最容易卡住。</p>
<h2 id="域名怎麼指到伺服器一筆-dns-紀錄">域名怎麼指到伺服器：一筆 DNS 紀錄</h2>
<p>域名系統（DNS）是「把人記得住的名字翻成機器用的 IP」的電話簿。你在網域註冊商買下 <code>example.com</code> 後，到它（或你用的 DNS 服務）的管理介面，加一筆 <strong>A record</strong>：</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">類型   名稱            值（指向）
</span></span><span class="line"><span class="ln">2</span><span class="cl">A      example.com     203.0.113.10      ← 你伺服器的公網 IP
</span></span><span class="line"><span class="ln">3</span><span class="cl">A      www             203.0.113.10</span></span></code></pre></div><p>A record 就是「這個名字 → 這個 IPv4」。加完後，全世界查 <code>example.com</code> 會拿到你的 IP、連過來。幾個常見卡點：</p>
<ul>
<li><strong>改了要等生效</strong>：DNS 有快取（TTL），改動可能幾分鐘到幾小時才全球生效，不是即時。</li>
<li><strong>A vs CNAME</strong>：A 指向 IP；CNAME 指向「另一個域名」（常用在指到 PaaS 給你的網址，如 <code>myapp.onrender.com</code>）。用 PaaS 時多半是設 CNAME——但裸網域 <code>example.com</code>（apex）依 DNS 規範不能掛 CNAME，只能用 A、或供應商的 ALIAS/flattening，子網域（<code>www</code>）才能 CNAME。這是 PaaS + 裸網域第一次上線的高頻卡點。</li>
<li><strong>域名 ≠ 伺服器</strong>：買域名跟租主機是兩件事、常在不同供應商。域名只是指標，指向哪台機器由 A/CNAME 決定。</li>
</ul>
<p>DNS 各紀錄類型的細節見 <a href="/blog/infra/knowledge-cards/dns/" data-link-title="DNS" data-link-desc="Domain Name System — 把域名轉成 IP 位址的系統，以及 A record、CNAME、NS、TTL 的角色">Infra DNS 卡</a>。</p>
<h2 id="https-的鎖頭從哪來tls-憑證">HTTPS 的鎖頭從哪來：TLS 憑證</h2>
<p><code>https://</code> 前面那個鎖頭代表兩件事：<strong>連線被加密</strong>（別人竊聽不到內容）、以及<strong>對方身分被驗證</strong>（你連的真的是 <code>example.com</code>、不是假冒的）。做到這兩點靠的是 <strong>TLS 憑證</strong>——一份由受信任的憑證頒發機構（CA）簽發、證明「這個域名是這台伺服器的」的檔案。</p>
<p>瀏覽器內建信任一批 CA。伺服器出示 CA 簽的憑證，瀏覽器驗章通過，鎖頭就亮、連線加密。憑證怎麼運作、CA 信任鏈的細節見 <a href="/blog/infra/knowledge-cards/ssl-tls/" data-link-title="SSL / TLS" data-link-desc="加密 client 與 server 之間通訊的協定，讓 HTTPS 成為可能。TLS 是 SSL 的後繼者，但 SSL 憑證的稱呼仍廣泛使用">Infra SSL/TLS 卡</a>。</p>
<h2 id="憑證怎麼拿lets-encrypt-讓它免費又自動">憑證怎麼拿：Let&rsquo;s Encrypt 讓它免費又自動</h2>
<p>以前憑證要花錢買，現在 <strong>Let&rsquo;s Encrypt</strong> 這個免費 CA 讓它變成一行指令。它用 ACME 協議自動驗證「你確實控制這個域名」（通常是讓它連你的 server 或設一筆 DNS 紀錄），驗過就簽發，且能自動續期（憑證有 90 天效期）。</p>
<ul>
<li><strong>自己顧機器（VPS）</strong>：用 <code>certbot</code> 之類的工具，指令大致是 <code>certbot --nginx -d example.com</code>——它自動取得憑證、改好 nginx 設定、排程續期。</li>
<li><strong>用 PaaS</strong>：平台通常自動幫你上憑證，你只要把域名指過去（設 CNAME）就有 HTTPS，完全不碰 certbot。</li>
</ul>
<h2 id="tls-在哪裡終結">TLS 在哪裡「終結」</h2>
<p>加解密這件事通常由 app 前面的一層代勞——nginx、負載平衡器、或 CDN 負責「TLS termination」：對外收 HTTPS、解密後用普通 HTTP 轉給後面的 app。所以你 app 本身常常只講 HTTP，HTTPS 是前面那層加上去的。反向代理 / LB 承擔這類職責的細節見 <a href="/blog/operations/01-load-balancing/reverse-proxy-responsibilities/" data-link-title="反向代理的職責" data-link-desc="釐清反向代理在單一入口後面承擔哪些職責、TLS 終止與路由怎麼設計、以及一條請求路徑上的 timeout 為什麼要由外到內遞減時回來讀">運行期維運 反向代理職責</a>。</p>
<h2 id="下一步">下一步</h2>
<p>域名跟 HTTPS 接上，服務就「對外像個正常網站」了。接著是讓服務本身好部署、好搬家——見 <a href="/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">十二要素基線</a>。用 IaC 把 DNS 與憑證納管（Route53 + ACM）的進階做法見 <a href="/blog/infra/05-core-services/" data-link-title="模組五：核心服務上 IaC" data-link-desc="資料庫、運算、儲存、load balancer 怎麼寫進基礎設施程式碼，以及上線順序">Infra 核心服務</a>。</p>
]]></content:encoded></item><item><title>十二要素基線</title><link>https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/</guid><description>&lt;p>十二要素（Twelve-Factor App）是一套「讓服務好部署、好搬家、好擴展」的基本紀律。它原本是 12 條，但對第一次上線的人，真正天天影響你的是其中幾條——它們的共通精神是&lt;strong>把「會變的東西」跟「code」分開&lt;/strong>，這樣同一份 code 才能在你的筆電、staging（上線前的測試環境）、prod 三個環境不改一行就跑起來。&lt;/p>
&lt;h2 id="設定進環境變數不寫死在-code-裡">設定進環境變數，不寫死在 code 裡&lt;/h2>
&lt;p>這是最重要的一條。資料庫位址、API 金鑰、外部服務 URL——這些&lt;strong>每個環境都不一樣&lt;/strong>的東西，不能寫死在 code 裡，要從&lt;strong>環境變數&lt;/strong>讀：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl"># 不要這樣（寫死，換環境要改 code）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">db = connect(&amp;#34;mysql://root:secret@localhost/app&amp;#34;)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"># 要這樣（從環境變數讀，換環境只換變數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">db = connect(env(&amp;#34;DATABASE_URL&amp;#34;))&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>好處：同一份 code 在本機讀到本機的 DB、在 prod 讀到 prod 的 DB，不用改 code、也不會把 prod 密鑰簽進 git。密鑰怎麼安全注入見 &lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">Backend secret 治理&lt;/a>。&lt;/p>
&lt;h2 id="process-無狀態資料放外面">process 無狀態，資料放外面&lt;/h2>
&lt;p>你的 app process 本身&lt;strong>不存資料&lt;/strong>——使用者 session、上傳的檔案、快取，都放到外部的後端服務（DB、Redis、物件儲存），不放在 app 的記憶體或本機磁碟。&lt;/p>
&lt;p>為什麼：這樣你才能隨時砍掉一個 app、重開一個、或同時開三個副本擋流量——因為資料不在 app 裡，砍了不會掉東西。這條是水平擴展的前提，深入見 &lt;a href="https://tarrragon.github.io/blog/operations/02-horizontal-scaling/stateless-design/" data-link-title="Stateless 設計原則" data-link-desc="要把服務改成能水平擴展的無狀態設計時，釐清什麼算「本機狀態」、哪些常見寫法會破壞無狀態、隱式狀態怎麼抓、以及定時 job 這種無狀態例外怎麼處理">運行期維運 無狀態設計&lt;/a>。&lt;/p>
&lt;h2 id="log-輸出到-stdout當成串流">log 輸出到 stdout，當成串流&lt;/h2>
&lt;p>不要讓 app 自己寫 log 檔、自己輪替。把 log 直接印到標準輸出（stdout），交給外面的平台去收集、儲存、查詢。這樣不管 app 跑在哪、幾個副本，log 都被統一收走，你不用去每台機器翻檔案。&lt;/p>
&lt;h2 id="明確宣告依賴開機即用">明確宣告依賴、開機即用&lt;/h2>
&lt;p>app 依賴哪些套件，要寫在 lockfile 裡（&lt;code>package-lock.json&lt;/code>、&lt;code>go.sum&lt;/code>、&lt;code>requirements.txt&lt;/code>），部署時照 lockfile 裝——不靠「機器上剛好有」。而且 app 要能&lt;strong>快速啟動、優雅關閉&lt;/strong>（收到停止信號先處理完手上的請求再退），這樣部署新版、自動重啟才順。&lt;/p>
&lt;h2 id="dev--prod-儘量一致">dev / prod 儘量一致&lt;/h2>
&lt;p>本機開發環境跟線上環境的差距越小，「在我電腦上能跑、上線卻壞」的機率越低。這條在你用舊版 runtime 的 client 環境時特別關鍵——本機要對齊線上的版本與行為，見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/10-prod-parity/" data-link-title="模組十：Prod Parity — 跨發行版與線上環境對齊" data-link-desc="工作站是 Arch 這種滾動最新版、但要開發的 client 線上跑的是凍結舊環境（PHP 7.2 / MySQL 5.7 / Debian）時回來讀 — dotfile 哲學怎麼跨 distro 落地、怎麼建對齊 prod 的 runtime">Dotfile 模組十：Prod Parity&lt;/a>。&lt;/p>
&lt;h2 id="判讀這些不是潔癖是省未來的痛">判讀：這些不是潔癖，是省未來的痛&lt;/h2>
&lt;p>每一條都對應一個「沒做就會在某個時刻痛」的場景：設定寫死 → 換環境或輪替密鑰時要改 code、還可能把密鑰簽進 git；process 有狀態 → 想加一台擋流量卻發現 session 掉了；log 寫檔 → 出事要 SSH 進每台機器撈。還有一條上 PaaS 當天就會撞的：&lt;strong>listen 在平台指派的 &lt;code>$PORT&lt;/code>&lt;/strong>——Heroku / Cloud Run 這類平台會給你一個環境變數指定 port，app 沒讀它、寫死自己的 port，就部署失敗。第一次上線可以先抓住「設定進環境變數」跟「process 無狀態」這兩條（上 PaaS 再加 &lt;code>$PORT&lt;/code>），其餘隨服務長大再補。&lt;/p>
&lt;h2 id="下一步">下一步&lt;/h2>
&lt;p>服務好部署了，接著常要決定「有狀態的那部分（資料庫）自己顧還是託管」——見 &lt;a href="https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架還是託管：以資料庫為例&lt;/a>。config 注入與 runtime 設定的進階做法見 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">Backend 部署平台&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>十二要素（Twelve-Factor App）是一套「讓服務好部署、好搬家、好擴展」的基本紀律。它原本是 12 條，但對第一次上線的人，真正天天影響你的是其中幾條——它們的共通精神是<strong>把「會變的東西」跟「code」分開</strong>，這樣同一份 code 才能在你的筆電、staging（上線前的測試環境）、prod 三個環境不改一行就跑起來。</p>
<h2 id="設定進環境變數不寫死在-code-裡">設定進環境變數，不寫死在 code 裡</h2>
<p>這是最重要的一條。資料庫位址、API 金鑰、外部服務 URL——這些<strong>每個環境都不一樣</strong>的東西，不能寫死在 code 裡，要從<strong>環境變數</strong>讀：</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"># 不要這樣（寫死，換環境要改 code）
</span></span><span class="line"><span class="ln">2</span><span class="cl">db = connect(&#34;mysql://root:secret@localhost/app&#34;)
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"># 要這樣（從環境變數讀，換環境只換變數）
</span></span><span class="line"><span class="ln">5</span><span class="cl">db = connect(env(&#34;DATABASE_URL&#34;))</span></span></code></pre></div><p>好處：同一份 code 在本機讀到本機的 DB、在 prod 讀到 prod 的 DB，不用改 code、也不會把 prod 密鑰簽進 git。密鑰怎麼安全注入見 <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">Backend secret 治理</a>。</p>
<h2 id="process-無狀態資料放外面">process 無狀態，資料放外面</h2>
<p>你的 app process 本身<strong>不存資料</strong>——使用者 session、上傳的檔案、快取，都放到外部的後端服務（DB、Redis、物件儲存），不放在 app 的記憶體或本機磁碟。</p>
<p>為什麼：這樣你才能隨時砍掉一個 app、重開一個、或同時開三個副本擋流量——因為資料不在 app 裡，砍了不會掉東西。這條是水平擴展的前提，深入見 <a href="/blog/operations/02-horizontal-scaling/stateless-design/" data-link-title="Stateless 設計原則" data-link-desc="要把服務改成能水平擴展的無狀態設計時，釐清什麼算「本機狀態」、哪些常見寫法會破壞無狀態、隱式狀態怎麼抓、以及定時 job 這種無狀態例外怎麼處理">運行期維運 無狀態設計</a>。</p>
<h2 id="log-輸出到-stdout當成串流">log 輸出到 stdout，當成串流</h2>
<p>不要讓 app 自己寫 log 檔、自己輪替。把 log 直接印到標準輸出（stdout），交給外面的平台去收集、儲存、查詢。這樣不管 app 跑在哪、幾個副本，log 都被統一收走，你不用去每台機器翻檔案。</p>
<h2 id="明確宣告依賴開機即用">明確宣告依賴、開機即用</h2>
<p>app 依賴哪些套件，要寫在 lockfile 裡（<code>package-lock.json</code>、<code>go.sum</code>、<code>requirements.txt</code>），部署時照 lockfile 裝——不靠「機器上剛好有」。而且 app 要能<strong>快速啟動、優雅關閉</strong>（收到停止信號先處理完手上的請求再退），這樣部署新版、自動重啟才順。</p>
<h2 id="dev--prod-儘量一致">dev / prod 儘量一致</h2>
<p>本機開發環境跟線上環境的差距越小，「在我電腦上能跑、上線卻壞」的機率越低。這條在你用舊版 runtime 的 client 環境時特別關鍵——本機要對齊線上的版本與行為，見 <a href="/blog/linux/dotfile/10-prod-parity/" data-link-title="模組十：Prod Parity — 跨發行版與線上環境對齊" data-link-desc="工作站是 Arch 這種滾動最新版、但要開發的 client 線上跑的是凍結舊環境（PHP 7.2 / MySQL 5.7 / Debian）時回來讀 — dotfile 哲學怎麼跨 distro 落地、怎麼建對齊 prod 的 runtime">Dotfile 模組十：Prod Parity</a>。</p>
<h2 id="判讀這些不是潔癖是省未來的痛">判讀：這些不是潔癖，是省未來的痛</h2>
<p>每一條都對應一個「沒做就會在某個時刻痛」的場景：設定寫死 → 換環境或輪替密鑰時要改 code、還可能把密鑰簽進 git；process 有狀態 → 想加一台擋流量卻發現 session 掉了；log 寫檔 → 出事要 SSH 進每台機器撈。還有一條上 PaaS 當天就會撞的：<strong>listen 在平台指派的 <code>$PORT</code></strong>——Heroku / Cloud Run 這類平台會給你一個環境變數指定 port，app 沒讀它、寫死自己的 port，就部署失敗。第一次上線可以先抓住「設定進環境變數」跟「process 無狀態」這兩條（上 PaaS 再加 <code>$PORT</code>），其餘隨服務長大再補。</p>
<h2 id="下一步">下一步</h2>
<p>服務好部署了，接著常要決定「有狀態的那部分（資料庫）自己顧還是託管」——見 <a href="/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架還是託管：以資料庫為例</a>。config 注入與 runtime 設定的進階做法見 <a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">Backend 部署平台</a>。</p>
]]></content:encoded></item><item><title>自架還是託管：以資料庫為例</title><link>https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/</guid><description>&lt;p>自己在 VPS 上跑資料庫，跟租一個託管資料庫（AWS RDS、Google Cloud SQL），帳面成本差很多——但那個差價買的是「你不用自己做的維運工作」，不是單純被多收錢。用資料庫當例子最清楚，因為 DB 是最不能出事、也最花維運的一塊。&lt;/p>
&lt;h2 id="成本結構為什麼差">成本結構為什麼差&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>&lt;/th>
 &lt;th>VPS 自己跑 DB&lt;/th>
 &lt;th>託管 RDS / Cloud SQL&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>DB 的錢&lt;/td>
 &lt;td>不另計帳單——跟 app 共用 VPS（但吃 RAM/IO）&lt;/td>
 &lt;td>獨立一筆——DB 自己一個 instance&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>計價項&lt;/td>
 &lt;td>一台 VPS 月租、全包&lt;/td>
 &lt;td>instance + 儲存 + 備份儲存 + I/O + 對外流量，分開計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>高可用（HA）&lt;/td>
 &lt;td>要自己搞&lt;/td>
 &lt;td>Multi-AZ（跨可用區）開下去大約 ×2&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>關鍵差別：VPS 上「DB 成本」不另計一條帳單，它跟 app 共用你本來就要付的那台機器；託管是&lt;strong>另外一條帳單&lt;/strong>，而且每單位 RAM/CPU 比裸 VPS 貴很多，因為價格裡包了維運層。純算 compute，同一個小 DB，託管常是自架的好幾倍到十幾倍。&lt;/p>
&lt;p>但「共用 VPS」不是真的零成本：DB（Postgres/MySQL）常態要 1–2GB+ RAM，跟 app 擠同一台小 VPS 容易 OOM 或 IO 互搶，實務上你得把 VPS 從 2GB 升到 4–8GB——那筆錢藏進了 VPS 帳單，只是不叫「DB 費用」。所以「便宜」要扣掉這段升規格的成本。&lt;/p>
&lt;blockquote>
&lt;p>以下是量級、不是報價，且雲端定價會變、看區域規格——決策前一定要去各家定價計算機用你的實際規格算。&lt;/p>&lt;/blockquote>
&lt;p>小專案常見的量級感：一台 2-4GB 的 VPS 全包月費個位數到二十幾鎂、DB 不另計；託管 DB 一個小 instance 一個月幾十鎂起、加儲存/備份/HA 後常落在幾十到上百鎂，而且是&lt;strong>疊在 app 主機費用之上&lt;/strong>。&lt;/p>
&lt;h2 id="那多付的錢在買什麼">那多付的錢在買什麼&lt;/h2>
&lt;p>差價買的是你&lt;strong>不做這些維運&lt;/strong>的代價：&lt;/p>
&lt;ul>
&lt;li>自動備份 + 時間點還原（point-in-time recovery）&lt;/li>
&lt;li>自動故障切換 / HA（主掛了自動起備）&lt;/li>
&lt;li>版本修補、監控、read replica 一鍵開&lt;/li>
&lt;li>半夜 DB 主機磁碟滿、掛掉時，有別人 on-call&lt;/li>
&lt;/ul>
&lt;p>在 VPS 上，以上每一條都是你的工作：你設備份、你&lt;strong>測還原&lt;/strong>（沒測過的備份等於沒有，見 &lt;a href="https://tarrragon.github.io/blog/going-live/backup-restore-basics/" data-link-title="備份與還原的地基" data-link-desc="有了線上資料、知道「要備份」但不確定備什麼、多久一次、以及為什麼「沒測過還原的備份等於沒有」時回來讀 — 備份的地基認識">備份與還原的地基&lt;/a>）、你修補、你處理 3am 事故；而且 VPS 一死、資料跟著死，除非你自己做了冗餘。&lt;/p>
&lt;h2 id="看-tco不看標價">看 TCO，不看標價&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>標價&lt;/strong>：VPS 明顯便宜（DB 不另計帳單、頂多升一階規格 vs 託管一個月幾十上百）。&lt;/li>
&lt;li>&lt;strong>含你的時間 + 資料遺失風險 + 停機損失（總持有成本 TCO）&lt;/strong>：一旦資料有價值（有營收、賠不起），託管常常反而划算——省下的是你不用當 DBA、不用扛半夜事故、不用賭「我的備份真的能還原嗎」。&lt;/li>
&lt;li>&lt;strong>分水嶺&lt;/strong>：自用 / 早期 / 極度省錢 / 你享受搞維運 → 偏自架；有營收資料 / 小團隊時間值錢 / 賠不起資料遺失 / 沒人顧 DB → 偏託管。&lt;/li>
&lt;/ul>
&lt;p>這條「自架帳單便宜、但主要成本在帳單外的人力」跟 &lt;a href="https://tarrragon.github.io/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">運行期維運 成本模型&lt;/a> 講的「自建與託管人力差 3 到 10 倍」是同一件事；兩條成本曲線的交叉點怎麼算，見 &lt;a href="https://tarrragon.github.io/blog/operations/08-cost-management/self-hosted-vs-cloud/" data-link-title="自架 vs 雲端的成本交叉點" data-link-desc="判斷該自架還是用雲端/商業方案時，看兩條成本曲線的交叉點、部署光譜的漸進選項、以及人力與 lock-in 這些不在帳單上的成本">運行期維運 自架 vs 雲端成本交叉點&lt;/a>。&lt;/p>
&lt;h2 id="別掉進二選一">別掉進二選一&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>便宜 VPS&lt;/strong>（如 Hetzner）把自架成本壓很低，省錢派很有吸引力。&lt;/li>
&lt;li>&lt;strong>託管也有便宜檔&lt;/strong>：不是只有 RDS/Cloud SQL 這種貴的——DigitalOcean Managed DB、Supabase、Neon、PlanetScale 有便宜甚至免費方案，別把「託管」直接等於「昂貴」。&lt;/li>
&lt;li>&lt;strong>Serverless DB&lt;/strong>（Aurora Serverless、Neon、PlanetScale）：流量低 / 尖峰型的按用量計費，離峰幾乎不花錢，小專案可能比固定 instance 更省。&lt;/li>
&lt;li>&lt;strong>折衷&lt;/strong>：DB 自架但放另一台獨立小 VPS（跟 app 分開、但不託管），隔離性有了、成本仍低。&lt;/li>
&lt;/ul>
&lt;h2 id="為什麼以資料庫為例特別代表性">為什麼「以資料庫為例」特別代表性&lt;/h2>
&lt;p>同樣的「自架 vs 託管」問題也發生在 cache、queue、物件儲存，但 DB 是最尖銳的——因為它&lt;strong>有狀態、最怕資料遺失&lt;/strong>。也因此，商業 prod 幾乎不會在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container&lt;/a> 裡跑正式 DB，而是用託管服務或獨立的資料節點（stateful 的保護與為何不隨手跑 DB container，見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">Backend 狀態儲存選型&lt;/a>）。無狀態的 app 可以隨便砍隨便開，有狀態的 DB 不行——這個差別決定了你多願意為「別人幫你顧它」付錢。&lt;/p></description><content:encoded><![CDATA[<p>自己在 VPS 上跑資料庫，跟租一個託管資料庫（AWS RDS、Google Cloud SQL），帳面成本差很多——但那個差價買的是「你不用自己做的維運工作」，不是單純被多收錢。用資料庫當例子最清楚，因為 DB 是最不能出事、也最花維運的一塊。</p>
<h2 id="成本結構為什麼差">成本結構為什麼差</h2>
<table>
  <thead>
      <tr>
          <th></th>
          <th>VPS 自己跑 DB</th>
          <th>託管 RDS / Cloud SQL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>DB 的錢</td>
          <td>不另計帳單——跟 app 共用 VPS（但吃 RAM/IO）</td>
          <td>獨立一筆——DB 自己一個 instance</td>
      </tr>
      <tr>
          <td>計價項</td>
          <td>一台 VPS 月租、全包</td>
          <td>instance + 儲存 + 備份儲存 + I/O + 對外流量，分開計</td>
      </tr>
      <tr>
          <td>高可用（HA）</td>
          <td>要自己搞</td>
          <td>Multi-AZ（跨可用區）開下去大約 ×2</td>
      </tr>
  </tbody>
</table>
<p>關鍵差別：VPS 上「DB 成本」不另計一條帳單，它跟 app 共用你本來就要付的那台機器；託管是<strong>另外一條帳單</strong>，而且每單位 RAM/CPU 比裸 VPS 貴很多，因為價格裡包了維運層。純算 compute，同一個小 DB，託管常是自架的好幾倍到十幾倍。</p>
<p>但「共用 VPS」不是真的零成本：DB（Postgres/MySQL）常態要 1–2GB+ RAM，跟 app 擠同一台小 VPS 容易 OOM 或 IO 互搶，實務上你得把 VPS 從 2GB 升到 4–8GB——那筆錢藏進了 VPS 帳單，只是不叫「DB 費用」。所以「便宜」要扣掉這段升規格的成本。</p>
<blockquote>
<p>以下是量級、不是報價，且雲端定價會變、看區域規格——決策前一定要去各家定價計算機用你的實際規格算。</p></blockquote>
<p>小專案常見的量級感：一台 2-4GB 的 VPS 全包月費個位數到二十幾鎂、DB 不另計；託管 DB 一個小 instance 一個月幾十鎂起、加儲存/備份/HA 後常落在幾十到上百鎂，而且是<strong>疊在 app 主機費用之上</strong>。</p>
<h2 id="那多付的錢在買什麼">那多付的錢在買什麼</h2>
<p>差價買的是你<strong>不做這些維運</strong>的代價：</p>
<ul>
<li>自動備份 + 時間點還原（point-in-time recovery）</li>
<li>自動故障切換 / HA（主掛了自動起備）</li>
<li>版本修補、監控、read replica 一鍵開</li>
<li>半夜 DB 主機磁碟滿、掛掉時，有別人 on-call</li>
</ul>
<p>在 VPS 上，以上每一條都是你的工作：你設備份、你<strong>測還原</strong>（沒測過的備份等於沒有，見 <a href="/blog/going-live/backup-restore-basics/" data-link-title="備份與還原的地基" data-link-desc="有了線上資料、知道「要備份」但不確定備什麼、多久一次、以及為什麼「沒測過還原的備份等於沒有」時回來讀 — 備份的地基認識">備份與還原的地基</a>）、你修補、你處理 3am 事故；而且 VPS 一死、資料跟著死，除非你自己做了冗餘。</p>
<h2 id="看-tco不看標價">看 TCO，不看標價</h2>
<ul>
<li><strong>標價</strong>：VPS 明顯便宜（DB 不另計帳單、頂多升一階規格 vs 託管一個月幾十上百）。</li>
<li><strong>含你的時間 + 資料遺失風險 + 停機損失（總持有成本 TCO）</strong>：一旦資料有價值（有營收、賠不起），託管常常反而划算——省下的是你不用當 DBA、不用扛半夜事故、不用賭「我的備份真的能還原嗎」。</li>
<li><strong>分水嶺</strong>：自用 / 早期 / 極度省錢 / 你享受搞維運 → 偏自架；有營收資料 / 小團隊時間值錢 / 賠不起資料遺失 / 沒人顧 DB → 偏託管。</li>
</ul>
<p>這條「自架帳單便宜、但主要成本在帳單外的人力」跟 <a href="/blog/operations/05-capacity-planning/cost-model/" data-link-title="成本模型" data-link-desc="把容量規劃的資源翻成錢時，釐清 on-demand、reserved、spot 三種計費模式的取捨、怎麼算單位請求成本、以及過度與不足配置各自的經濟代價">運行期維運 成本模型</a> 講的「自建與託管人力差 3 到 10 倍」是同一件事；兩條成本曲線的交叉點怎麼算，見 <a href="/blog/operations/08-cost-management/self-hosted-vs-cloud/" data-link-title="自架 vs 雲端的成本交叉點" data-link-desc="判斷該自架還是用雲端/商業方案時，看兩條成本曲線的交叉點、部署光譜的漸進選項、以及人力與 lock-in 這些不在帳單上的成本">運行期維運 自架 vs 雲端成本交叉點</a>。</p>
<h2 id="別掉進二選一">別掉進二選一</h2>
<ul>
<li><strong>便宜 VPS</strong>（如 Hetzner）把自架成本壓很低，省錢派很有吸引力。</li>
<li><strong>託管也有便宜檔</strong>：不是只有 RDS/Cloud SQL 這種貴的——DigitalOcean Managed DB、Supabase、Neon、PlanetScale 有便宜甚至免費方案，別把「託管」直接等於「昂貴」。</li>
<li><strong>Serverless DB</strong>（Aurora Serverless、Neon、PlanetScale）：流量低 / 尖峰型的按用量計費，離峰幾乎不花錢，小專案可能比固定 instance 更省。</li>
<li><strong>折衷</strong>：DB 自架但放另一台獨立小 VPS（跟 app 分開、但不託管），隔離性有了、成本仍低。</li>
</ul>
<h2 id="為什麼以資料庫為例特別代表性">為什麼「以資料庫為例」特別代表性</h2>
<p>同樣的「自架 vs 託管」問題也發生在 cache、queue、物件儲存，但 DB 是最尖銳的——因為它<strong>有狀態、最怕資料遺失</strong>。也因此，商業 prod 幾乎不會在 <a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container</a> 裡跑正式 DB，而是用託管服務或獨立的資料節點（stateful 的保護與為何不隨手跑 DB container，見 <a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">Backend 狀態儲存選型</a>）。無狀態的 app 可以隨便砍隨便開，有狀態的 DB 不行——這個差別決定了你多願意為「別人幫你顧它」付錢。</p>
<h2 id="下一步">下一步</h2>
<p>決定了哪些自己顧之後，凡是你自己顧的（尤其 DB），下一個必修是備份——見 <a href="/blog/going-live/backup-restore-basics/" data-link-title="備份與還原的地基" data-link-desc="有了線上資料、知道「要備份」但不確定備什麼、多久一次、以及為什麼「沒測過還原的備份等於沒有」時回來讀 — 備份的地基認識">備份與還原的地基</a>。自建 vs 託管的完整選型理論見 <a href="/blog/backend/00-service-selection/" data-link-title="模組零：後端服務選型" data-link-desc="從需求類型判斷資料庫、快取、訊息佇列、觀測與部署平台的選型方向">Backend 模組零</a>。</p>
]]></content:encoded></item><item><title>備份與還原的地基</title><link>https://tarrragon.github.io/blog/going-live/backup-restore-basics/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/going-live/backup-restore-basics/</guid><description>&lt;p>備份真正的能力是「&lt;strong>出事時還原得回來&lt;/strong>」，不是「有沒有在備」。這推翻了對備份最常見的誤解：以為「有排程在跑 backup」就安全了。還原能不能成功，只有真的試過才知道。&lt;/p>
&lt;h2 id="為什麼沒測過還原的備份等於沒有">為什麼「沒測過還原的備份等於沒有」&lt;/h2>
&lt;p>備份會&lt;strong>無聲地失敗&lt;/strong>：排程壞了沒人發現、備出來的檔案是空的或損毀、備了但少備了關鍵那張表、加密備份的金鑰弄丟了解不開。這些在你「需要還原」的那一刻才會爆——而那一刻通常是最糟的時刻（資料已經沒了）。&lt;/p>
&lt;p>所以該有的紀律是：&lt;strong>定期真的做一次還原演練&lt;/strong>——把備份拉到一個乾淨環境、還原、確認資料完整、app 接得上。演練同時量「還原花多久」——一份要跑半天才還原完的備份，對某些服務等於不可用，這個還原耗時就是還原時間目標（RTO）。演練過的備份才是資產，沒演練過的只是「你以為有」的安全感。各資料庫的還原演練實作見 vendor drills，如 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/hands-on/pitr-restore-drill/" data-link-title="PostgreSQL PITR Restore Drill" data-link-desc="PostgreSQL base backup、WAL archive、target time restore、validation query 與 RPO / RTO evidence 的操作說明">PostgreSQL PITR 演練&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/mysql/hands-on/backup-restore-drill/" data-link-title="MySQL Backup Restore Drill" data-link-desc="MySQL logical dump、physical backup frame、binlog position、restore validation 與 RPO / RTO evidence">MySQL 備份還原演練&lt;/a>。&lt;/p>
&lt;h2 id="該備什麼不該備什麼">該備什麼、不該備什麼&lt;/h2>
&lt;p>備份的對象是「弄丟了重建不回來的東西」，不是全部：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>要備&lt;/strong>：資料庫內容、使用者上傳的檔案、以及不在版控裡的 secret / 設定值來源（依十二要素 secret 不簽進 git、第三方 key 撤了就撤了，重建不回來）——這些是&lt;strong>唯一副本&lt;/strong>，沒了就真沒了。&lt;/li>
&lt;li>&lt;strong>不用備&lt;/strong>：你的 app code（在 git 裡）、container image（在 &lt;a href="https://tarrragon.github.io/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">registry&lt;/a> 這個 image 倉庫裡）、能重跑一次就長回來的東西。這些有別的來源，備份它們是浪費。&lt;/li>
&lt;/ul>
&lt;p>判準：問「這東西弄丟了，我能不能從別的地方重建？」能 → 不用備；不能 → 要備。這也呼應&lt;a href="https://tarrragon.github.io/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">十二要素&lt;/a>的「process 無狀態、資料放外面」——正因為狀態集中在少數幾個地方（DB、物件儲存），要備份的範圍才清楚。&lt;/p>
&lt;h2 id="幾條地基原則">幾條地基原則&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>多久一次，看你賠得起丟多少&lt;/strong>：每天備 = 最多丟一天的資料。丟一天能接受就每天；不能接受就要更頻繁、或用能還原到任意時間點的機制（point-in-time recovery）。這個「能容忍丟多少」就是還原點目標的白話版。&lt;/li>
&lt;li>&lt;strong>備份別跟正本放一起&lt;/strong>：跟資料庫放同一台機器的備份，機器掛了兩個一起死。要放到不同機器 / 不同區域 / 不同供應商。常見的口訣是「3 份副本、2 種媒介、1 份異地」。&lt;/li>
&lt;li>&lt;strong>舊備份要留一段時間&lt;/strong>：只留最新一份的問題是——如果資料是幾天前就悄悄壞了、才發現，你最新的備份也已經是壞的。留一段歷史才能還原到「壞掉之前」。&lt;/li>
&lt;/ul>
&lt;h2 id="這也是自架-vs-託管的一個關鍵差異">這也是「自架 vs 託管」的一個關鍵差異&lt;/h2>
&lt;p>託管資料庫（RDS / Cloud SQL）把上面這些大部分自動化了：自動排程、異地儲存、point-in-time recovery、還原按幾個鍵。自己在 VPS 上跑 DB，這些&lt;strong>全是你的工作&lt;/strong>——這正是&lt;a href="https://tarrragon.github.io/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架 vs 託管&lt;/a>那筆「帳單外成本」裡最重的一項。常被低估的就是這塊：DB container 跑起來很容易，備份、測還原、異地、保留策略才是難的部分。&lt;/p>
&lt;h2 id="下一步">下一步&lt;/h2>
&lt;p>備份是你自己顧任何有狀態元件時的底線。往上，接手一個別人留下的環境時，第一件事往往就是盤點「它到底有沒有能還原的備份」——見 &lt;a href="https://tarrragon.github.io/blog/infra/takeover/legacy-database-backup-migration/" data-link-title="無 SSH 環境的資料庫備份與變更管理" data-link-desc="在只有 phpMyAdmin 或有限遠端連線的無 SSH 環境裡，怎麼建立可靠的資料庫備份策略、schema 變更紀律與還原演練流程">Infra 接手：舊資料庫備份與遷移&lt;/a>。&lt;/p>
&lt;p>備份是自己顧任何有狀態元件的底線。往上的深度內容見各系列：服務選型理論 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/" data-link-title="模組零：後端服務選型" data-link-desc="從需求類型判斷資料庫、快取、訊息佇列、觀測與部署平台的選型方向">Backend 模組零&lt;/a>、雲端地基 &lt;a href="https://tarrragon.github.io/blog/infra/" data-link-title="Infra 基礎設施建置指南" data-link-desc="從零循序漸進把雲端基礎設施做起來 — IaC、身分憑證、網路地基、環境分離、核心服務、可觀測性、自動化 review 與治理習慣，含怎麼在組織內推動">Infra&lt;/a>、運維與成本 &lt;a href="https://tarrragon.github.io/blog/operations/" data-link-title="運行期維運 — 服務在 production 怎麼活下來" data-link-desc="負載平衡、水平擴展、流量管控、服務探活、容量規劃、高可用、突發流量、成本管理 — 服務上線後運行期的工程基礎">DevOps&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>備份真正的能力是「<strong>出事時還原得回來</strong>」，不是「有沒有在備」。這推翻了對備份最常見的誤解：以為「有排程在跑 backup」就安全了。還原能不能成功，只有真的試過才知道。</p>
<h2 id="為什麼沒測過還原的備份等於沒有">為什麼「沒測過還原的備份等於沒有」</h2>
<p>備份會<strong>無聲地失敗</strong>：排程壞了沒人發現、備出來的檔案是空的或損毀、備了但少備了關鍵那張表、加密備份的金鑰弄丟了解不開。這些在你「需要還原」的那一刻才會爆——而那一刻通常是最糟的時刻（資料已經沒了）。</p>
<p>所以該有的紀律是：<strong>定期真的做一次還原演練</strong>——把備份拉到一個乾淨環境、還原、確認資料完整、app 接得上。演練同時量「還原花多久」——一份要跑半天才還原完的備份，對某些服務等於不可用，這個還原耗時就是還原時間目標（RTO）。演練過的備份才是資產，沒演練過的只是「你以為有」的安全感。各資料庫的還原演練實作見 vendor drills，如 <a href="/blog/backend/01-database/vendors/postgresql/hands-on/pitr-restore-drill/" data-link-title="PostgreSQL PITR Restore Drill" data-link-desc="PostgreSQL base backup、WAL archive、target time restore、validation query 與 RPO / RTO evidence 的操作說明">PostgreSQL PITR 演練</a>、<a href="/blog/backend/01-database/vendors/mysql/hands-on/backup-restore-drill/" data-link-title="MySQL Backup Restore Drill" data-link-desc="MySQL logical dump、physical backup frame、binlog position、restore validation 與 RPO / RTO evidence">MySQL 備份還原演練</a>。</p>
<h2 id="該備什麼不該備什麼">該備什麼、不該備什麼</h2>
<p>備份的對象是「弄丟了重建不回來的東西」，不是全部：</p>
<ul>
<li><strong>要備</strong>：資料庫內容、使用者上傳的檔案、以及不在版控裡的 secret / 設定值來源（依十二要素 secret 不簽進 git、第三方 key 撤了就撤了，重建不回來）——這些是<strong>唯一副本</strong>，沒了就真沒了。</li>
<li><strong>不用備</strong>：你的 app code（在 git 裡）、container image（在 <a href="/blog/ci/knowledge-cards/container-registry/" data-link-title="Container Registry" data-link-desc="說明容器產物儲存、權限與推進流程在 CD 中的責任">registry</a> 這個 image 倉庫裡）、能重跑一次就長回來的東西。這些有別的來源，備份它們是浪費。</li>
</ul>
<p>判準：問「這東西弄丟了，我能不能從別的地方重建？」能 → 不用備；不能 → 要備。這也呼應<a href="/blog/going-live/twelve-factor-baseline/" data-link-title="十二要素基線" data-link-desc="服務能上線了、但一換機器 / 換環境就出狀況、設定散在各處、log 不知道去哪找時回來讀 — 讓服務好部署好搬家的幾條基本紀律">十二要素</a>的「process 無狀態、資料放外面」——正因為狀態集中在少數幾個地方（DB、物件儲存），要備份的範圍才清楚。</p>
<h2 id="幾條地基原則">幾條地基原則</h2>
<ul>
<li><strong>多久一次，看你賠得起丟多少</strong>：每天備 = 最多丟一天的資料。丟一天能接受就每天；不能接受就要更頻繁、或用能還原到任意時間點的機制（point-in-time recovery）。這個「能容忍丟多少」就是還原點目標的白話版。</li>
<li><strong>備份別跟正本放一起</strong>：跟資料庫放同一台機器的備份，機器掛了兩個一起死。要放到不同機器 / 不同區域 / 不同供應商。常見的口訣是「3 份副本、2 種媒介、1 份異地」。</li>
<li><strong>舊備份要留一段時間</strong>：只留最新一份的問題是——如果資料是幾天前就悄悄壞了、才發現，你最新的備份也已經是壞的。留一段歷史才能還原到「壞掉之前」。</li>
</ul>
<h2 id="這也是自架-vs-託管的一個關鍵差異">這也是「自架 vs 託管」的一個關鍵差異</h2>
<p>託管資料庫（RDS / Cloud SQL）把上面這些大部分自動化了：自動排程、異地儲存、point-in-time recovery、還原按幾個鍵。自己在 VPS 上跑 DB，這些<strong>全是你的工作</strong>——這正是<a href="/blog/going-live/self-host-vs-managed-db/" data-link-title="自架還是託管：以資料庫為例" data-link-desc="在 VPS 上自己跑一個 DB container 很便宜、看到 RDS / Cloud SQL 一個月要幾十鎂而猶豫時回來讀 — 成本差在哪、差價其實在買什麼">自架 vs 託管</a>那筆「帳單外成本」裡最重的一項。常被低估的就是這塊：DB container 跑起來很容易，備份、測還原、異地、保留策略才是難的部分。</p>
<h2 id="下一步">下一步</h2>
<p>備份是你自己顧任何有狀態元件時的底線。往上，接手一個別人留下的環境時，第一件事往往就是盤點「它到底有沒有能還原的備份」——見 <a href="/blog/infra/takeover/legacy-database-backup-migration/" data-link-title="無 SSH 環境的資料庫備份與變更管理" data-link-desc="在只有 phpMyAdmin 或有限遠端連線的無 SSH 環境裡，怎麼建立可靠的資料庫備份策略、schema 變更紀律與還原演練流程">Infra 接手：舊資料庫備份與遷移</a>。</p>
<p>備份是自己顧任何有狀態元件的底線。往上的深度內容見各系列：服務選型理論 <a href="/blog/backend/00-service-selection/" data-link-title="模組零：後端服務選型" data-link-desc="從需求類型判斷資料庫、快取、訊息佇列、觀測與部署平台的選型方向">Backend 模組零</a>、雲端地基 <a href="/blog/infra/" data-link-title="Infra 基礎設施建置指南" data-link-desc="從零循序漸進把雲端基礎設施做起來 — IaC、身分憑證、網路地基、環境分離、核心服務、可觀測性、自動化 review 與治理習慣，含怎麼在組織內推動">Infra</a>、運維與成本 <a href="/blog/operations/" data-link-title="運行期維運 — 服務在 production 怎麼活下來" data-link-desc="負載平衡、水平擴展、流量管控、服務探活、容量規劃、高可用、突發流量、成本管理 — 服務上線後運行期的工程基礎">DevOps</a>。</p>
]]></content:encoded></item></channel></rss>