Hasura Metadata Migration & 判斷流程:初學者完整指南

Published August 5, 2025 by 徐培鈞
Web API

使用 Hasura 的過程中,你可能注意到:

有時候你沒有新增任何資料表,只是調整了一個角色的權限、修改了一個 relationship,卻突然在 metadata/ 資料夾中多了一堆 YAML 檔案。

這些,其實就是 Hasura 的 Metadata Migration

很多剛接觸 Hasura 的初學者會疑惑:

「我只是調整一下設定,為什麼要做 Migration?」
「Metadata 到底是什麼?我什麼時候該管它?」

這篇文章將一步一步帶你理解:

  • 什麼是 Metadata Migration?
  • 和 Database Migration 有什麼不同?
  • 有哪些常見場景會觸發 Metadata 變動?
  • 實務上怎麼判斷「我到底要不要做 Migration?」

什麼是 Hasura 的 Metadata?

Hasura 其實不只是單純幫你轉接 GraphQL 和 PostgreSQL,它還維護了一層 「中介設定」,記錄你對 GraphQL API 的調整。

這層設定就叫做 Metadata,裡面包括:

舉例說明指定角色(如 user、admin)可以讀取哪些欄位
舉例說明建立 Table 之間的關聯,如 one-to-many
舉例說明把外部 GraphQL 加進來當擴充 API
舉例說明自訂的 mutation 或 query(例如呼叫 webhook)
舉例說明某表格的 insert/update/delete 發生後自動觸發事件
舉例說明使用 PostgreSQL function 並包裝成 GraphQL

這些設定都是 Hasura 自己儲存在 metadata 系統中,並不屬於你原本的 PostgreSQL schema。

Metadata Migration 是什麼?

在 Hasura 中,Metadata Migration 指的是:把你對 Hasura 設定的所有改動「具體地記錄下來」,並儲存成一組可重複執行的 YAML / JSON 檔案

這個機制就像你在版本控制程式碼一樣,也能對 Hasura 的設定進行版本管理、變更追蹤與跨環境部署。

為什麼需要 Metadata Migration?

Hasura 除了管理資料表(Database)外,還有一層很重要的 GraphQL API 設定層,例如:

  • 某個角色能否看到某個欄位?
  • 這兩張表要不要建立關聯?
  • 某個 mutation 是不是觸發了一個 Webhook?
  • 有沒有整合外部 GraphQL schema?

這些行為設定就屬於 Hasura Metadata,而這些設定的變動如果不被紀錄,將導致:

  • ❶ 團隊成員之間設定不一致
  • ❷ 測試與正式環境的 API 行為不同
  • ❸ 上線後回不去,也無法追蹤改了什麼

為了解決這些問題,Hasura 提供了「Metadata Migration 機制」來把所有變動記錄下來。

Metadata Migration 能幫你做什麼?

當你使用 Hasura CLI 搭配 hasura metadata export,它會自動從 Hasura 伺服器抓取目前所有設定,並存成一組檔案(通常是 YAML 格式):

metadata/
├── actions.yaml
├── allow_list.yaml
├── cron_triggers.yaml
├── databases/
   └── default/
       ├── tables/
          └── ...
       ├── functions.yaml
       ├── remote_relationships.yaml
       └── ...
├── query_collections.yaml
└── version.yaml

這些檔案構成了「你目前的 Hasura 設定快照」。

Metadata Migration 的三大核心功能

說明每次變更都能 commit 到 Git,用 Pull Request 審查
說明不怕別人覆蓋你設定,大家都能保持一致
說明將 dev 上的設定 export,再 apply 到 staging / production

搭配 Hasura CLI 的操作指令有哪些?

Hasura CLI 提供一整套針對 Metadata Migration 的工具,操作流程如下:

用途匯出當前 Hasura 設定為檔案
補充說明通常在修改後執行一次,備份設定
用途將本地 metadata 套用到目標 Hasura
補充說明用於部署、跨環境同步
用途比對本地與伺服器設定的差異
補充說明可用來審查有哪些修改
用途強制讓 Hasura 重新載入 metadata
補充說明偶爾操作後需 reload 才會生效

舉個例子更清楚

假設你今天做了以下操作:

  1. 在 Hasura Console 中,為 user 表新增了一個 select 權限,給 user 角色。
  2. 修改 user 表與 order 表之間的 relationship。
  3. 建立了一個新的 action:submitSurvey

這些操作本身不會改動資料表結構,但它們會改變 GraphQL API 的行為。因此:

  • 這些設定就會被紀錄在 metadata/ 資料夾中
  • 你可以使用 Git commit 起來
  • 日後用 hasura metadata apply 部署到正式環境

也就是說,你的設定就像程式碼一樣,變得「可被追蹤」、「可被還原」、「可被部署」。

Metadata Migration 不是備份,是「基礎建設的一部分」

很多初學者會誤以為 metadata export 僅僅是一種備份,其實不是。

它是一種完整的設定描述檔,用來:

  • 建構 Hasura 行為邏輯
  • 同步多個環境一致性
  • 作為 CI/CD 自動部署設定的重要輸入

就像你在寫前端程式時會 commit components/,在 Hasura 開發時,也應該把 metadata/ 一併納入 Git 追蹤。

當然可以,以下是你指定段落 「三、Hasura 的兩種 Migration 對比」 的完整擴寫版本,除了表格對比外,也補充了概念背景、實務差異、舉例說明、同步策略與初學者常犯的誤解,讓這段教學更完整:

Hasura 的兩種 Migration 對比

在 Hasura 中,「Migration」這個詞其實指的是兩種不同層級的變更紀錄機制:

  1. Database Migration:針對「資料庫結構」的異動,如新增表格、修改欄位、建立索引等
  2. Metadata Migration:針對「Hasura API 行為設定」的異動,如角色權限、表格關聯、remote schema 等

這兩者的資料來源不同、影響層級不同、儲存位置不同,但都可以透過 Hasura CLI 被版本化、追蹤與部署。

兩種 Migration 對照表

資料位置PostgreSQL 資料庫
包含的內容資料表(table)、欄位(column)、索引(index)、主鍵、外鍵、資料型別變更、constraint 等
產出的檔案migrations/
常見格式up.sql, down.sql, config.yaml
資料位置Hasura Metadata 層
包含的內容權限(permissions)、relationships、remote schema、actions、event triggers 等
產出的檔案metadata/
常見格式YAML / JSON

什麼情況會產生哪一種 Migration?

Hasura 會根據你在 Console 上「實際修改的內容」來自動決定產出哪一種 Migration:

Migration 類型Database Migration
Migration 類型Database Migration
Migration 類型Metadata Migration
Migration 類型Metadata Migration
Migration 類型Metadata Migration
Migration 類型Metadata Migration

有時候你一個操作會同時改動兩層(例如新增 table 時,同時設定 role 權限),那麼 Hasura CLI 會同時產生 兩種 Migration 檔案

實務範例:新增一張 user 表,並設定權限

1. 使用 Hasura Console 建立 user 表,欄位為:

  • id: uuid
  • name: text
  • created_at: timestamptz

2. 為角色 user 加上 select 權限,允許讀取 name 欄位

這時,Hasura CLI 會自動產生:

  • migrations/20240805120000_create_user_table/
    包含 up.sql, down.sql → 對應表格建立
  • metadata/tables.yaml, metadata/permissions.yaml
    更新了角色權限設定

這種情況下就會同時產生 Database + Metadata Migration

Hasura 如何知道要產出哪種 Migration?

Hasura CLI 的行為是這樣設計的:

  • 你在 CLI 開啟的 Console 中進行操作hasura console 指令開的頁面)
  • 勾選左下角的 This is a migration(預設會打勾)
  • 那麼 Hasura 會針對你每次在 Console 上的異動,自動產生:
  • up.sql / down.sql(若為資料庫異動)
  • metadata/ YAML(若為 Hasura 設定異動)

補充提醒

這個行為只有在你用 CLI 開啟 Console 時才會生效。

如果你使用雲端版的 Hasura Console(cloud.hasura.io),就不會自動產生 migration 檔案

延伸說明:兩種 Migration 為何要區分?

Hasura 之所以把兩種 Migration 分開,是因為它們的「變動性質」與「部署方式」不同:

Database MigrationPostgreSQL 資料庫
Metadata MigrationHasura 本身的 API 層設定
Database Migration高(可能導致資料損毀)
Metadata Migration較低(設定錯誤最多造成 API 錯誤)
Database Migration執行 SQL 指令
Metadata Migration套用設定檔(非 SQL)
Database Migration需要正確撰寫 down.sql
Metadata MigrationGit 還原 metadata + apply
Database Migration結構調整:新增欄位、改型別、加索引等
Metadata Migration權限變更、建立 API 邏輯、設定關聯等

實務上如何管理這兩者?

✅ 建議作法:

  • 每次操作 Hasura Console 時,都用 CLI 開啟(確保會產生 migration)
  • 改完設定後,一定要 hasura metadata export
  • Git commit 時,一起 commit migrations/metadata/
  • 部署到其他環境時:先 apply migrations/,再 apply metadata/

常見會產生 Metadata Migration 的情境

Hasura 中的 Metadata 是用來記錄你「對 GraphQL API 行為的設定」。

這些設定雖然不會改動 PostgreSQL 資料表本身,但卻會影響使用者能不能存取某張表、能不能看到某個欄位、API 能不能呼叫某個 webhook 等等。

以下操作都會產生 metadata:

對應的 Metadata 設定檔案permissions.yaml(位於 metadata/tables/ 中)
對應的 Metadata 設定檔案tables.yaml(也位於 metadata/tables/ 中)
對應的 Metadata 設定檔案remote_schemas.yaml
對應的 Metadata 設定檔案actions.yaml、action_permissions.yaml
對應的 Metadata 設定檔案event_triggers.yaml
對應的 Metadata 設定檔案functions.yaml

實務例子說明

✅ 修改權限(最常見)

在 Hasura Console 中,當你給 user 角色新增 select 權限時,其實背後會被轉換成類似這樣的設定:

select_permissions:
  - role: user
    permission:
      columns:
        - id
        - name
      filter: {}

這些設定會寫進 metadata/tables/<your-table>.yaml 裡,屬於 metadata 的一部分。

✅ 建立 Relationship

當你把 order.user_iduser.id 建立關聯(one-to-many)時,Hasura 會記錄這段關係,寫入 object_relationships 欄位:

object_relationships:
  - name: user
    using:
      foreign_key_constraint_on: user_id

這也會產生 metadata 變動。

✅ 加入 Remote Schema

例如你想整合 Stripe 或自建 GraphQL API,只要輸入 URL 並點「Add Remote Schema」,Hasura 就會把設定寫入:

remote_schemas:
  - name: Stripe
    definition:
      url: https://api.stripe.com/graphql

這屬於 metadata 設定,也必須用 metadata export 匯出。

📌 提醒:即使只是「刪除一個權限」或「改了一個 relationship 名稱」,也會改變 metadata,而這類改動如果沒記錄下來,就無法部署到其他環境,也無法追蹤誰改了什麼。

實務判斷流程:什麼情況要做 Metadata Migration?

Hasura 的 Migration 系統分為 Database(資料庫結構)與 Metadata(API 設定)兩種,因此你每次在 Hasura 上操作時,都需要先判斷:這次的改動到底是哪一類?

快速判斷流程圖

我現在做的事情是什麼?

├─► 改動資料表結構?(加欄位、建索引) 
         建立 Database Migration(migrations/)

├─► 改的是 Hasura 設定?(改權限、建 relationship) 
         建立 Metadata Migration(metadata/)

└─► 只是塞資料?(INSERT / UPDATE / DELETE) 
          不需要 Migration(屬於 runtime 資料)

建議做 Metadata Migration 的具體情境

以下這些改動,都是 Hasura 內部 GraphQL 行為的設定,一定要產生 metadata 並加入版本控制:

為什麼需要 Metadata Migration?會改變 GraphQL API 是否能查詢這張表
為什麼需要 Metadata Migration?沒記錄下來的話,部署後行為會不一致
為什麼需要 Metadata Migration?影響 order { user { ... } } 是否能查
為什麼需要 Metadata Migration?會改變 API 能不能 query 外部資料源
為什麼需要 Metadata Migration?避免設定被覆蓋或部署後遺失

哪些操作不需要 Migration?

原因屬於資料層,非設定層
原因同上
原因屬於執行時資料操作,無需記錄設定
原因屬於「使用 API」,不屬於「建 API」

關鍵觀念總結

Metadata Migration 是「設定行為的紀錄」;Database Migration 是「結構變更的紀錄」;資料操作則不需要 Migration。

如果你是多人團隊開發 Hasura,建議每次設定完畢都執行:

hasura metadata export
git add metadata/
git commit -m "feat: 新增 user 角色的權限設定"

這樣才能確保後續部署、測試、審查都不會出錯。

明白了,下面是我針對你原本提供的內容和意圖,重新撰寫成更自然流暢、具文章感的版本的「六、Metadata Migration 怎麼做?」章節。它會保留完整的知識量與技術細節,但語氣會更像是閱讀一篇教學文章,而不是逐條說明的手冊:

Metadata Migration 怎麼做?

在 Hasura 中,除了記錄資料庫結構變化的 Database Migration,還有一個經常被初學者忽略,卻同樣重要的機制:Metadata Migration

它負責追蹤所有與 Hasura API 設定有關的變動,例如角色權限、資料表關聯、remote schemas、自定義 actions 等,這些都不是寫入 PostgreSQL,而是存在 Hasura 自己的 metadata 層。

那麼問題來了:這些設定要怎麼被版本控制?又該如何部署到 staging 或 production 環境?這就是 Metadata Migration 的作用。

不是所有操作都會自動記錄:關於 hasura metadata export

許多使用者會有一個直覺:「我透過 Hasura Console 操作了權限或關聯,設定應該已經自動儲存到本地 metadata/ 了吧?」

但實際上,這取決於你是透過哪種方式開啟 Console

  • 如果你是使用 hasura console(CLI 開的 Console),那麼好消息是:Hasura CLI 會在你操作 metadata 的同時,自動將設定寫入你本地的 metadata/ 資料夾,不需要額外匯出。
  • 但如果你是透過 cloud.hasura.io 的雲端 Console,或手動輸入網址打開 Hasura UI,那麼這些變動只會寫入伺服器,不會更新你本地的檔案。這時你就需要手動執行:
hasura metadata export

這個指令會從 Hasura Server 匯出當前的設定狀態,並寫入本地專案的 metadata/ 資料夾中,方便你進行版本控制與部署。

即使你是用 CLI 開的 Console,我也建議在 commit 前養成習慣性執行一次 export,確保所有設定都有被寫入,避免被 CLI 寫入失敗卻沒察覺。

把 metadata 加進 Git,是團隊協作的關鍵

Hasura 的 metadata 設定會以 YAML(或 JSON)格式儲存在 metadata/ 資料夾中,這些檔案可以被版本控制,讓團隊成員可以追蹤設定改動、發 PR 審查,並且保證 staging 與 production 環境的設定保持一致。

當你完成設定變更並確認 metadata 檔案正確後,記得:

git add metadata/
git commit -m "feat: 新增 user 角色的權限與 table 關聯設定"

這是整合 Hasura 到多人協作流程中最關鍵的一步。

部署:將 metadata 套用到其他環境

當你在本地測試無誤後,接下來就是部署 metadata 到 staging 或 production。只需要一行指令,就可以將你本地的設定套用到指定的 Hasura 伺服器:

hasura metadata apply \
  --endpoint https://staging.example.com \
  --admin-secret your-secret

這個動作會將 metadata/ 裡的所有檔案同步上去,直接影響 GraphQL API 的權限、關聯與行為。

請注意:這會完整覆蓋遠端伺服器上的 metadata 設定,因此建議部署前先比對差異,避免誤蓋掉其他人的改動。

如何部署前比對差異:hasura metadata diff

在實務上,我們通常會在 apply 之前加上一個檢查步驟,使用:

hasura metadata diff \
  --endpoint https://staging.example.com \
  --admin-secret your-secret

這會顯示你本地設定與 staging 伺服器上的設定差異,像是某個欄位的權限不一致、某個關聯未同步,這樣能有效避免「部署後才發現破壞了某些功能」的情況。

這個指令也非常適合在 PR Review 階段做為審查工具,讓 reviewer 清楚看到 metadata 改動的具體內容。

reload:當 apply 後設定沒生效怎麼辦?

偶爾你可能會遇到一種情況:你已經套用 metadata,但 Console 上的 API 行為卻沒有變化。這時候,很可能是 Hasura Server 的 metadata 沒有自動 reload。

別擔心,Hasura 提供一個指令可以強制重新載入 metadata:

hasura metadata reload \
  --endpoint https://your-env.com \
  --admin-secret your-secret

這可以幫助你解決 API 行為沒同步、或發生 metadata inconsistent 錯誤的問題。

整體開發與部署流程總結

  1. 使用 hasura console 進行 metadata 設定(或使用 Cloud UI 並記得 export)
  2. 操作後執行 hasura metadata export(確認更新)
  3. metadata/ 檔案加入 Git
  4. 部署前用 hasura metadata diff 比對環境差異
  5. hasura metadata apply 套用到遠端
  6. 必要時執行 hasura metadata reload 確保生效

這整套流程聽起來繁瑣,但只要建立好習慣,很快你會發現 Hasura 的設定與部署其實比傳統後端更可控、更透明。

結語:Metadata Migration 是團隊協作的防撞牆

Hasura 的 Metadata 是建立你 GraphQL API 行為的根基。

Metadata Migration 則是保護這些設定在多人協作下不會「互相打架」、不會「環境不一致」的關鍵機制。

初學者最容易忽略這一層,等到 staging 和 production 行為不一樣才發現問題。

掌握好 Metadata Migration,不僅能提升開發效率,更能讓你團隊的部署更穩定、更可靠。