
Dagster の“ネイティブ統合”が効いた話(dlt / dbt + リバースETL)
こんにちは!Scene Live bq事業本部のまっすーです。
2025年からデータサイエンティスト兼データエンジニアとして、Scene Liveに中途入社しました。bqというサービスのLLMを用いた検証・研究をおこなったり、プロダクトに関するデータ収集から利活用までの『データ基盤』を作ったりしています。
連載:「モダンデータスタック続編」第 3 回 / 全 3 回
第 1 回:なぜ Airflow から Dagster に乗り換えたのか
第 2 回:Dagster 移行、500 テーブル超を止めずに引っ越した話
はじめに
データ関連の連載、最終回です。
第 1 回で 「なぜ Dagster に乗り換えたのか」、第 2 回で 「どうやって 500 テーブル超を引っ越したのか」を書きました。今回はその仕上げで、「移行してから何が良くなったのか」、特に第 1 回で挙げた ネイティブ統合 が、実際どう効いているかの話です。
「ネイティブ統合」と言われてもピンとこないと思うので、Airflow 時代と何が違うのか、何ができるようになったのかを、できるだけ具体的に書きます。
この記事の前提(用語の整理)
第 1 回・第 2 回で出てきた用語(Cloud Composer / CRJ / CRS / BigQuery / Airflow / Dagster / Asset / Pipes / dbt / dlt)は引き続き使います。本記事で初めて深く触れる用語を以下に整理します。
Asset Lineage(アセット系統図): Asset 同士の依存関係を 1 枚の DAG(有向非巡回グラフ)として可視化したもの。「このテーブルを作るには、どのテーブルが必要で、その元はどこから来ているか」が一目で分かる
dlt(data load tool): Python で「外部からデータを取り込む」処理を書く OSS。dbt と似た開発体験で取り込みパイプラインが書ける。第 1 回でも軽く触れた通り、Dagster 移行と同時に導入した
@dbt_assets: dagster-dbt が提供する Python デコレータ。dbt プロジェクトを 1 行(に近い記述)で 「dbt のモデル 1 つ = Dagster の Asset 1 つ」 に変換してくれる
@dlt_assets: 同様に dagster-dlt が提供するデコレータ。dlt の取り込み source 1 つを Dagster の Asset 1 つに対応させる
スキーマドリフト: 取り込み元(API や DB)のテーブル構造が、知らないうちに変わってしまうこと。カラムが増えた・減った・型が変わった等。dlt はこれを検知して通知できる
「ネイティブ統合」って結局何が違うの?
第 1 回で「dbt / dlt / リバース ETL とのネイティブ統合が強力だった」と書きました。これがピンと来ないと、本記事は楽しめないので、まずここを丁寧に。
Airflow 時代の「外部実行」と、Dagster の「ネイティブ統合」を並べてみます。
Airflow 時代(外部実行):
Airflow の DAG 内
└─ task: dbt を実行する
└─ 内部: dbt build というシェルコマンドを叩く
└─ dbt が 500 を超えるモデルを順番に処理(Airflow からは見えない)
Airflow から見えるのは「dbt build というタスクが成功したか失敗したか」の 1 ビット情報だけ。中で 500 を超えるモデルがどう動いたかは、dbt 側のログを別途見にいかないと分かりません。
Dagster(ネイティブ統合):
Dagster の Definitions
└─ @dbt_assets: dbt プロジェクトを「Asset の集まり」として宣言
└─ Dagster は 500 モデル 1 つ 1 つを「個別の Asset」として認識
└─ どのモデルが何秒で動いたか・どこで失敗したかが Asset 画面で全部見える
つまり、Dagster がツールを「外から呼ぶ」のではなく、ツールの単位(dbt モデル / dlt source)がそのまま Dagster の管理単位(Asset)になる。これが「ネイティブ統合」です。

以下のように、DagsterのUIの中で、依存関係(Lineage)が見える、しかもasset単位で。

この差が、実運用でどう効くかを 3 つに分けて見ていきます。
dbt: 1 モデル = 1 Asset の威力
500 を超える dbt モデルが、500 個の Asset として Dagster の UI に並ぶ。これだけ聞くと「いやそれ多すぎでしょ」と思うかもしれません。実際、最初は私もそう思いました。
ところが運用してみると、「全部 Asset」だからこそできることが圧倒的に多かったんです。
個別リトライができる: 500 モデルのうち 1 つだけが失敗したとき、その 1 モデルだけを再実行できる(Airflow 時代は「dbt build を全部やり直す」になりがちだった)
実行時間がモデル単位で見える: どのモデルが遅いか・最近遅くなったかが Asset 画面でひと目で分かる
宣言は驚くほど短く、5 行ほどで dbt プロジェクトの全モデルが Dagster Asset になります。
@dbt_assets(manifest=Path("target/manifest.json"))
def my_dbt_assets(context, dbt: DbtCliResource):
yield from dbt.cli(["build"], context=context).stream()
以下はモデル・Asset単位で実行時間や他Assetとの関係等が見えている画像です。

dlt: 1 source = 1 Asset で取り込みも統一
dlt 側も同じ構造です。dlt で書いた取り込み source(API / CloudSQL / GCS など)が、そのまま Dagster の Asset として並びます。
これがなぜ嬉しいかというと、取り込み(dlt)と変換(dbt)が同じ Asset の世界で繋がるから。
[dlt source: notion_pages] → [dbt model: bronze_notion]
→ [dbt model: silver_notion]
→ [dbt model: gold_notion]
この矢印が、Dagster の Asset Lineage に自動で現れます。dlt と dbt を別々のツールとして書いているのに、Dagster の中では 1 枚の DAG に繋がる。
そして、第 2 回で書いた スキーマドリフトの Slack 通知 も、ネイティブ統合のおかげで実装が楽でした。dlt が「あ、カラムが増えた」と検知すると、Dagster の Asset イベントとしてその情報が拾えるので、そこから Slack を叩くだけ。Airflow 時代だったら、dlt(当時はカスタムスクリプト)の中で通知ロジックを書く必要があったところです。
リバース ETL: 出口まで Asset で繋ぐ
うちでは Bronze → Silver → Gold という 3 階層でデータを加工した最後に、業務 SaaS やプロダクト DB にデータを書き戻すというステップがあります。これがリバース ETL です。
このリバース ETL のツールも、Dagster の Asset として統合されています。つまり、
[dlt 取り込み] → [dbt 変換 (Bronze〜Gold)] → [リバース ETL: SaaS / DB へ書き戻し]
この一連の流れが、1 つの Asset Lineage として Dagster の UI で見られる。データが「外から来て、加工されて、外に出ていく」全部が 1 枚で見えるわけです。

これは Airflow 時代だと不可能でした。dlt 相当のスクリプト・dbt・リバース ETL 相当のスクリプトを、別々の DAG タスクとして並べることはできても、「データ単位の依存関係」としては繋がっていなかったからです。
“全部 Asset” だからできること
ここまで dbt / dlt / リバース ETL を個別に見てきましたが、ネイティブ統合の本当の威力は 「3 つを同じ単位で扱える」 ことです。
具体的に効いているシーンを 3 つだけ。
1. 失敗時の影響範囲が秒で特定できる
朝、Slack にエラー通知が来る。Dagster の UI を開くと、どの Asset が失敗して、どの下流 Asset が止まっているかが 1 画面で見える。「あ、このダッシュボードに使ってる Gold テーブルまで波及してるな」が即座に分かる。

Airflow 時代は「失敗した DAG を見る → 中の dbt のログを見る → どのモデルが失敗したか特定 → 影響範囲を SQL で調査」という流れで、軽く 30 分〜1 時間かかっていました。これが数分になりました。
2. リトライが Asset 単位
失敗した Asset だけを Dagster の UI からポチっと再実行できる。Airflow 時代は「DAG 全体を再実行」「dbt build をやり直す」など、必要以上に大きい単位で動かすことが多かった。
3. 観測性が統一される
dlt の取り込み時間も、dbt のモデル実行時間も、リバース ETL の書き戻し時間も、全部同じ Asset 画面で見られる。「最近、データが揃うのが遅くなってきたな」と思ったら、Asset の実行時間履歴を眺めれば原因が分かる。
実際にコストはどう変わったか
第 1 回で「Composer の固定料金が重かった」と書きました。その答え合わせを、最後に少しだけ。
移行前後で、Composer がやっていた仕事 (オーケストレーター本体) にかかるインフラ費用を比較すると、こうなりました。具体的な金額は伏せて、移行前 (Cloud Composer の月額) を 100 とした相対値 で書いていきます。

つまり、 Composer 時代を基準に 約 4 割削減 (▲42%) 。月で見ると Composer の固定料金がまるごと消えて、代わりに Dagster の Cloud Run (常駐 CRS 3 つ) + Cloud SQL (バックエンド DB) が新規発生した結果、約 6 割のコストで同じ仕事ができている、という構図です。
Cloud SQL が新たに増えているのは、Dagster は内部状態 (実行履歴・スケジュール・センサー状態など) を PostgreSQL に保存する設計 だからです。Composer はフルマネージドで内部に PostgreSQL を持っていたので、「Composer の月額」にこの分が含まれていただけで、Dagster を自前ホストする以上は、PostgreSQL のコストは “Dagster の一部” として読んでおくのがフェアですね。
しかも、これでも まだ調整中です 。移行直後はリソース設定を保守的に振っていたぶん、Cloud Run のコストが高めに出ていました。直近 1〜2 週間でも、CRS の min_instance (常時起動するインスタンス数) や CPU/メモリ設定をチューニングして少しずつ下げてきていて、第 1 回で言っていた “削減 ”は、まだ終わっていない というのが正直なところです。
並行運用や本番デプロイで 3 日止めたぶんの “痛み” はあったわけですが、オーケストレーター本体のコストを長期的に約 4 割削減できる のは、規模が大きくなるほど効いてくるはずで、ここは移行して良かったと思っています。
※ なお、データ基盤全体ではこれ以外に GCS / BigQuery などのコストもありますが、それらは Dagster 移行とは別の要因 (データ量の増減・dlt 取り込み方式変更など) で動くため、ここでは触れていません。
ネイティブ統合の限界
ここまでメリットを並べてきましたが、当然限界もあります。誠実に書いておきます。
Dagster バージョンに引きずられる: dagster-dbt は Dagster のメジャーアップデートで API が変わることがある。dbt 側は問題なく動いていても、Dagster 側で書き直しが必要になることが起こりうる
ツール固有の機能が薄まる: dlt / dbt それぞれが持っている細かい機能(特殊な実行モードや CLI オプション)が、ネイティブ統合の薄いラッパー越しでは使いにくいことがある。素の dbt build ではできることが、@dbt_assets 経由だとひと工夫必要、みたいな
学習コストは結局かかる: Asset の概念に慣れるまでは、「dbt は dbt として、dlt は dlt として書ければいいじゃん」と感じるはず。Asset の世界観に乗ったときの恩恵が大きいぶん、乗るまでのハードルはある
ただし、これらの限界は AI コーディング環境(Claude Code + dagster-io/skills プラグイン)でかなり緩和される、というのは第 1 回でも書いた通りです。書き換えが必要なときも、AI が「ここをこう変えればいい」と教えてくれるので、自力ですべて追う必要はありません。
連載のおわりに
3 回にわたって、Airflow から Dagster への移行の話を書いてきました。
第 1 回: なぜ乗り換えたか(コスト・設計思想・ネイティブ統合)
第 2 回: どう引っ越したか(環境別の段階移行と、3 日止めた話)
第 3 回(本記事): 移行後に何が良くなったか(ネイティブ統合の威力)
データ基盤の “作った話” は前回の note 記事で書 きましたが、“作ってからの話” は今回の連載でようやくまとめられました。データ基盤は作って終わりじゃなく、運用しながら育てていくものなので、これからも何かやらかしたら正直に書こうと思います。
最後まで読んでいただきありがとうございました。
なお、次回は連載をいったん離れて、単発で 「データの消費者は『ヒト』だけじゃない ─ AI ネイティブなデータ基盤の実態」 という記事を書く予定です。今回の連載で整えた基盤を、LLM がデータの消費者として登場し始めている話 ─ 例えば GCP のコストデータを LLM が分析して SRE 的なアドバイスを Slack に投げてきたり、評価ロジックの劣化を LLM が見張っていたり ─ の事例を紹介します。
その後に、LLM 運用基盤としての Langfuse に関する連載を予定しています。お楽しみに!
連載目次
第 3 回: Dagster の“ネイティブ統合”が効いた話(dlt / dbt + リバース ETL)(本記事)
まだまだ発展途上のデータ基盤。これからも生成AI・LLMを使った改善を続けていきます!
データ基盤に興味がある方、LLMを活用した開発やデータ分析に興味がある方、ぜひお話ししましょう。
▼Scene Live 採用情報
▼bq事業のエンジニア採用