タクシーアプリ『GO』の分析基盤を開発運用している伊田です。本記事では、Google Cloud の Dataform の運用改善について紹介します。
※ 本記事の対象読者は Dataform を利用している方を対象にしています
この記事は、GO Advent Calendar 2025 17日目の記事です。
はじめに
データ基盤チームでは、BigQuery 上でデータの変換処理を行うために Dataform を利用しています。今回は Dataform を運用していく中で改善した2つの事例を紹介します。 1つ目は Cloud Composer (Airflow マネージドサービス。以後 Airflow と表記) で実行される Dataform の可視化についてです。データ基盤チームでは、Dataform の定時実行を Airflow で管理しています。この Airflow で実行されるタスクが、BigQuery のどのテーブルに対応しているのかを可視化する仕組みについて紹介します。 2つ目はDataform CLI コマンドで、意図しない実行を防止するための仕組みについてです。
Airflow で実行される Dataform の可視化
背景
データ基盤では Dataform と Dataform 以外の処理が混在し、それらの処理の依存関係や実行時間制御を一貫して行いたいため、Dataform の実行機能は用いず、Airflowから実行しています。
その際に、Airflow から実行する Dataform の処理単位をどのように揃えるかという問題があります。基本的には Dataform の処理には一定の粒度でタグをつけているので、Airflow からはタグ単位で実行します。 例えば、前処理用のタグを実行するタスク、データマート生成処理用のタグを実行するタスクなどです。
課題
Dataform の処理をタグ単位で Airflow から実行する場合、Dataform 観点では、どのテーブルの処理がどの DAG で呼ばれているのかわからないです。 同様に Airflow 側の観点では、指定したタグによってどの処理が実行されるのかわからないため、Dataform 側のソースコードを見る必要があります。
このことは、障害発生時に関連する DAG の特定がしづらく、レビュー時も処理範囲が把握しづらいという問題があります。
対応
アイデアとしては、Dataform および Airflow の両方の情報を組み合わせて、Airflow のタスク → 対応する Dataform のタグ → 対応する BigQuery のテーブルの対応関係を一覧化します。
ここでは、まず、対応関係のマッピング処理について説明し、次に全体の運用フローを説明します。
対応関係のマッピング
Dataform の情報取得
dataform compile --timeout=5m --json > manifest.json を実行して、データの依存関係やタグ情報を出力します。
Airflow の情報取得
DagBag を使って対象の DAG のソースコードを解析し、Airflow から Dataform を実行するための Operator である DataformCreateWorkflowInvocationOperator を探索し、Airflow のタスクと Dataform のタグの対応関係を取得します。
DagBag は DAG を管理するためのクラスで、DagBag を通じて DAG の情報にアクセスできます。
ただし、DagBag を使うには Airflow の環境構築が必要で、各種パスを通す必要があります。
参考までに、DagBag のドキュメントおよび DagBag を利用する際に参考にしたサイトのリンクを載せておきます。
マッピング処理
Airflow の情報によって、Airflow のタスクと Dataform のタグの対応関係がわかります。 Dataform の情報によって、タグと BigQuery のテーブルの対応関係がわかります。 これらを組み合わせることで、Airflow のタスク → Dataform のタグ → BigQuery のテーブルの対応関係を一覧化できます。
このマッピング処理では一覧として見るために csv ファイルと、依存関係を可視化するために mermaid 記法で記述した markdown を生成しています。 mermaid 記法は GitHub 上でレンダリングされるため、GitHub 上で依存関係を可視化できます。
運用フロー
運用フローとしては以下のようになります。
- Airflow の DAG 作成または修正を行い、Pull Request を作成します。
- Pull Request が作成されると、GitHub Actions が発火し、Airflow と Dataform の対応関係を生成するマッピング処理を実行して push します。
- レビュワーはマッピング結果を参考にして、Airflow の DAG をレビューします。
このようにすることで、レビュワーは Airflow と Dataform の対応関係を把握しながらレビューできるようになります。
補足として、レビュー時はこのマッピング結果が最新となりますが、Dataform 側の変更によってマッピング結果が変わる場合もあります。例えば、指定されたタグ配下に処理対象が増える場合は、Dataform の Pull Request は作成されますが、Airflow の Pull Request は作成されません。この場合、マッピング結果が古くなってしまいます。これを防ぐために GitHub Actions を日次実行で動かし、マッピング情報を更新しています。
結果
結果として、テーブルの生成処理がどの DAG で実行されているのか検索できるようになり、 レビュー時も Dataform のコードを追わなくても、どの処理が実行されるのか把握しやすくなりました。
下記は依存関係を mermaid 記法によってGitHub上でレンダリングされた例です。

Dataform CLI コマンドの誤実行防止
背景
Dataform に限らずですが、テーブルのスキーマ変更により backfill や洗い替えをしたい場合、通常のスケジュール実行とは別の操作を本番環境に対して実施することがあります。このような場合、Google Cloud の Dataform の UI 上から実行するか、Dataform CLI コマンドを利用してテーブルの再生成を行います。
課題
データ基盤チームでは、backfill や洗い替えの際には Dataform CLI で、 tags (もしくは actions)オプションを利用して、処理する SQLX を指定して本番作業を実施する運用ルールとなっています。ただ、過去に tags オプションを誤って指定せずに実行してしまい、Dataform の全ての定義が処理対象となってしまい、データ加工の全 SQLX が本番環境で実行されるというインシデントが発生したことがあります。このインシデントを機に Dataform CLI をラッパーしたスクリプトを導入し、誤実行防止の仕組みを導入しました。
誤実行例
過去にあった事例として、以下のようにまず dry-run オプションで処理対象を確認し、その後に本実行を行う手順で本番作業をしていました。
$ dataform run \ --timeout=5m \ --dry-run \ --tags=xxx \ --vars="hoge=fuga"
その後、担当者はあらかじめ用意していたコマンドに対して dry-run オプションをコメントアウトし、コンソールにコピペして実行しました。
$ dataform run \ --timeout=5m \ # --dry-run \ --tags=xxx \ --vars="hoge=fuga"
するとどうでしょうか。
本来の意図としては、dry-run オプションが外れる想定でしたが、シェルの解釈としては dry-run 以降のオプションが無効になり、tags および vars オプションが無効になって、全処理がデフォルトの変数で実行されてしまいました。
実際にシェルとして解釈されたコマンドは以下です。
$ dataform run --timeout=5m \# --dry-run --tags=xxx --vars="hoge=fuga"
結果的には担当者がすぐに間違いに気づきキャンセルしたため、大事には至りませんでしたが、これを機に誤実行防止の仕組みを導入することにしました。
対応
アイデアとしては、dataform run コマンドを実行する際に actions や tags のオプションが指定されていない場合は dataform run を実行しないようなラッパースクリプトを用意しました。
具体的には、本番作業を実施する人の環境差分を吸収するために必要なソースコードをコンテナ化し、本番作業する際はこのコンテナを利用して dataform run を実行するようにしました。
ここでは、まず、ラッパースクリプトについて説明し、次に本番作業する際のフローを説明します。
ラッパースクリプト
ラッパースクリプトのファイル名は dataform_wrapper.sh とします。この時、利用者からは dataform run 実行時に、ラッパースクリプトが実行されるようにします。そのため、Dockerfile では以下のようにして、dataform のバイナリをラッパースクリプトで置き換えています。
※ 該当部分のみ抜粋
FROM node:20-bookworm-slim (中略) RUN mv /usr/local/bin/dataform /usr/local/bin/dataform_org COPY ./dataform_wrapper.sh /usr/local/bin/dataform RUN chmod +x /usr/local/bin/dataform
このようにすることで、利用者はラッパースクリプトを意識せずに dataform run コマンドを実行できます。これによって、actions や tags オプションが指定されていない場合はエラーメッセージを出力して終了し、actions や tags オプションが指定されている場合は、/usr/local/bin/dataform_org を呼び出して元の dataform コマンドを実行します。
このようにすることで、dataform run コマンドで全処理が実行されることを防止できます。
本番作業フロー
本番作業を実施する際のフローは以下のようになります。
- sqlx の修正およびリリース手順書の作成を行い、Pull Request を作成します。
- Pull Request がマージされると、GitHub Actions が発火し、dataform のソースコードおよびラッパースクリプトを含むコンテナイメージがビルドされ、Artifact Registry にプッシュされます。
- 本番作業を実施する際は、該当のコンテナイメージを利用して
dataform runコマンドを実行します。
このようにすることで、GitHub のソースコードを正として、本番環境に処理を実行できるようになり、かつ、誤実行防止の仕組みを導入できます。
結果
導入前は誤実行が半年に1回くらいの割合で発生していたのが、この仕組みを導入したことで、誤実行の件数がゼロになりました。
おわりに
本記事では、Dataform の2つの運用改善について紹介させて頂きました。 この改善は実際に Dataform を運用していく中で発生した課題に対応したものです。この改善によって、
- Airflow, Dataform, BigQuery の対応関係が可視化でき、レビューや調査が楽になった
- 本番リリース作業が安全になった
ということを実感しています。 細かい知見とはなりますが、Dataform および Airflow を利用している方の参考になれば幸いです。