Snowflake App RuntimeでElementaryのレポートをDockerなしでホスティングしてみた
さがらです。
以前、Snowpark Container Servicesを使ってElementaryのレポートをWebで閲覧できる環境を構築する記事を書きました。
また、その後Databricksを使っているチーム向けに、Databricks Appsで同じことができないか試した記事も書きました。
SPCS版では、Dockerfileの作成・Docker imageのビルド・Image Repositoryへのpush・Compute Poolの作成・snow spcs service createによるサービス作成が必要でした。Elementaryのレポートは実体としてはelementary_report.htmlとelementary_output.jsonという静的ファイルなので、コンテナイメージを自前で作ってpushするのは正直少し過剰に感じていました。
そんな中、Node.js(Next.js中心)のアプリケーションをSnowflake上に直接デプロイできるSnowflake App RuntimeがPublic Previewでリリースされています。
Snowflake App Runtimeを使うと、Dockerfileも、Docker imageのビルドも、Image Repositoryも使わずに、Snowflake CLIのsnow app deployだけでアプリをデプロイ可能です。今回は、Elementaryのレポートホスティングという同じ課題を、Snowflake App Runtimeで解決できるか試してみました。
機能概要
Snowflake App Runtimeは、Node.js(特にNext.js)で書かれたフルスタックWebアプリケーションを、Snowflakeのセキュリティ境界内に直接デプロイできる機能です。データベースへのアクセスもAPIレイヤーやETLを介さず、アプリケーションコードから直接Snowflakeのテーブルへクエリできます。
デプロイの流れとしては、snow app setupでプロジェクトの初期化を行い、snow app deployでアップロード・ビルド・デプロイまでを一括で実行します。デプロイが完了すると、以下のような認証付きURLが発行され、Snowflakeへログインしているユーザーであればブラウザからそのままアクセスできます。
https://<id>-<org>-<account>-<region>.snowflakecomputing.app/
内部的には、Application Serviceという専用のオブジェクトタイプとしてSnowpark Container Services上で稼働しています。従来のSPCSサービスとはオブジェクトタイプが異なるため、SHOW SERVICESでは表示されず、SHOW APPLICATION SERVICESで確認する点に注意が必要です。
制限事項
- 2026年7月7日時点ではPublic Preview機能です。GAまでに仕様が変わる可能性があります
- Trialアカウントでは利用できません(有料アカウントが必要です)
- Snowflake CLI 3.17以降が必須です。古いバージョンでは
snow app setupコマンド自体が存在しません - Public Previewの間は、マネージドのCompute Poolが強制的に使用されます
snow app setup実行時にデータベース・スキーマを明示しない場合、既定では個人用データベース(USER$<ユーザー名>のような形式)に配置されます。個人用データベースに配置したアプリは他ロールへ共有できません- デプロイのたびに既存のバージョンを上書きするのではなく、新しいバージョンが作成される仕様です
- 対応スタックはNode.js/Next.js中心で、Python対応は計画中とのことです(2026年7月7日時点)
自動一時停止とコストについて
Snowflake App Runtimeでデプロイしたアプリは、内部的にはApplication Serviceとして稼働します。そのため、コスト面ではApplication Serviceのライフサイクルも意識しておく必要があります。
Application ServiceにはAUTO_SUSPEND_SECSという自動一時停止設定がありますが、デフォルトは0、つまり自動一時停止は無効です。検証用途で作成したアプリをそのまま放置すると、意図せずcomputeコストが発生し続ける可能性があるため注意が必要です。
AUTO_SUSPEND_SECSはCREATE APPLICATION SERVICEまたはALTER APPLICATION SERVICEで設定できます。ただし、2026年7月7日時点で確認した限り、snow app deployのオプションやsnowflake.ymlでデプロイ時に直接指定する方法は見当たりませんでした。
そのため、必要に応じてデプロイ後に以下のように設定します。
ALTER APPLICATION SERVICE
SAGARA_SNOWFLAKE_APPS.PUBLIC.ELEMENTARY_REPORT_APP
SET
AUTO_RESUME = TRUE,
AUTO_SUSPEND_SECS = 900;
上記の例では、15分間非アクティブだった場合にApplication Serviceが自動的に一時停止されます。なお、AUTO_SUSPEND_SECSに指定できる最小の非ゼロ値は300秒です。
一時停止中のApplication Serviceはコンテナが停止し、computeの課金も停止します。検証環境や利用頻度が低い社内向けアプリでは、snow app deploy後にAUTO_SUSPEND_SECSを設定しておくと安心です。
参考までにApp Runtimeの単価について、Consumption Tableでは2026年7月7日時点で下図のように記載がありました。

前提条件
今回の検証は、以下が完了している前提で進めます。
- Snowflake: 有料アカウント(Trialアカウントは不可)。Snowflake App Runtimeが利用可能なアカウント
- 本機能のステータス: 2026年7月7日時点ではPublic Preview
- Snowflake CLI: 3.17以降がインストール済みで、対象アカウントに接続できる状態
- Node.js: ローカルでの動作確認用にインストール済み
- Elementaryのレポートファイル:
elementary_report.htmlとelementary_output.jsonが生成済み
今回作成するSnowflakeオブジェクトの名前は以下で統一します。
| オブジェクト | 名前 |
|---|---|
| Database | SAGARA_SNOWFLAKE_APPS |
| Schema | PUBLIC |
| Warehouse | SAGARA_SNOWFLAKE_APPS_QUERY_WH |
| App name | elementary_report_app |
| Application Service | ELEMENTARY_REPORT_APP |
事前準備
Snowflake CLIのバージョン・接続確認
まず、Snowflake CLIのバージョンが3.17以降であることを確認します。
snow --version
snow app setupコマンドが存在するかも確認しておきます。(古いバージョンの場合は、アップグレードしてください。)
snow app setup --help
続いて、対象アカウントへの接続を確認します。
snow connection test
複数の接続を使い分けている場合は、接続名を指定します。以降のコマンドでも必要に応じて--connection <connection_name>を付けてください。
snow connection test --connection <connection_name>
接続情報が問題なく表示されればOKです。
Node.jsのバージョンも確認します。
node --version
Elementaryのレポートファイルを確認
dbtプロジェクトのルートに、Elementaryのレポートが生成済みである前提で進めます。
dbt_project/
├── dbt_project.yml
├── models/
├── edr_target/
│ ├── elementary_report.html
│ └── elementary_output.json
試してみた
1. App Runtime用ディレクトリを作成
ローカルにApp Runtime用のディレクトリを作成し、Elementaryのレポートファイルをコピーします。
mkdir -p elementary-report-app/public
elementary_report.htmlはindex.htmlにリネームしてコピーします。これにより、アプリのURL直下にアクセスしただけでElementaryレポートを表示できるようになります。
cp edr_target/elementary_report.html elementary-report-app/public/index.html
cp edr_target/elementary_output.json elementary-report-app/public/elementary_output.json
cd elementary-report-app
最終的なディレクトリ構成は以下のとおりです。各ファイルはこれから作成していきます。
elementary-report-app/
├── app.yml
├── package.json
├── server.mjs
├── snowflake.yml # snow app setup で生成
└── public/
├── index.html
└── elementary_output.json
2. server.mjsを作成
Snowflake App Runtime上でHTTPサーバーを起動するserver.mjsを作成します。SPCS版ではNginxコンテナで静的ファイルを配信していましたが、今回はNode.jsの最小HTTPサーバーで配信します。
elementary-report-app/server.mjsとして以下の内容で保存します。
// server.mjs
import http from "node:http";
import { readFile, stat, readdir } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// App Runtime の実行パッケージ root をドキュメントルートにする
const documentRoot = __dirname;
const port = Number(process.env.PORT || process.env.SERVER_PORT || 8080);
const host = "0.0.0.0";
const mimeTypes = {
".html": "text/html; charset=utf-8",
".json": "application/json; charset=utf-8",
".js": "text/javascript; charset=utf-8",
".css": "text/css; charset=utf-8",
".svg": "image/svg+xml",
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".ico": "image/x-icon",
".map": "application/json; charset=utf-8",
".txt": "text/plain; charset=utf-8",
};
async function listFilesRecursive(dir, baseDir = dir) {
const entries = await readdir(dir, { withFileTypes: true });
const files = [];
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
const relativePath = path.relative(baseDir, fullPath);
if (entry.isDirectory()) {
const childFiles = await listFilesRecursive(fullPath, baseDir);
files.push(...childFiles);
} else {
files.push(relativePath);
}
}
return files;
}
function safeResolve(urlPath) {
const decodedPath = decodeURIComponent(urlPath.split("?")[0]);
// ルートアクセス時は index.html を返す
const normalizedPath = decodedPath === "/" ? "/index.html" : decodedPath;
const filePath = path.normalize(path.join(documentRoot, normalizedPath));
// ディレクトリトラバーサル対策
if (!filePath.startsWith(documentRoot)) {
return null;
}
return filePath;
}
const server = http.createServer(async (req, res) => {
try {
if (!req.url) {
res.writeHead(400, {
"content-type": "text/plain; charset=utf-8",
});
res.end("Bad Request");
return;
}
console.log(JSON.stringify({
message: "request",
url: req.url,
cwd: process.cwd(),
dirname: __dirname,
documentRoot,
}));
if (req.url === "/healthz") {
res.writeHead(200, {
"content-type": "text/plain; charset=utf-8",
});
res.end("ok");
return;
}
// デバッグ用: 実行環境内に存在するファイル一覧を確認する
if (req.url === "/__debug/files") {
const files = await listFilesRecursive(documentRoot);
res.writeHead(200, {
"content-type": "application/json; charset=utf-8",
});
res.end(JSON.stringify({
cwd: process.cwd(),
dirname: __dirname,
documentRoot,
files,
}, null, 2));
return;
}
const filePath = safeResolve(req.url);
console.log(JSON.stringify({
message: "resolved file path",
url: req.url,
filePath,
}));
if (!filePath) {
res.writeHead(403, {
"content-type": "text/plain; charset=utf-8",
});
res.end("Forbidden");
return;
}
const fileStat = await stat(filePath);
if (!fileStat.isFile()) {
res.writeHead(404, {
"content-type": "text/plain; charset=utf-8",
});
res.end("Not Found");
return;
}
const body = await readFile(filePath);
const ext = path.extname(filePath).toLowerCase();
const contentType = mimeTypes[ext] || "application/octet-stream";
res.writeHead(200, {
"content-type": contentType,
"cache-control": "no-store",
});
res.end(body);
} catch (err) {
console.error(JSON.stringify({
message: "request failed",
url: req.url,
error: err instanceof Error ? err.message : String(err),
}));
res.writeHead(404, {
"content-type": "text/plain; charset=utf-8",
});
res.end("Not Found");
}
});
server.listen(port, host, () => {
console.log(JSON.stringify({
message: "Elementary report server started",
url: `http://${host}:${port}`,
cwd: process.cwd(),
dirname: __dirname,
documentRoot,
}));
});
ポイントは以下です。
PORTまたはSERVER_PORT環境変数からポート番号を読み取り、未設定時は8080をデフォルトにしています0.0.0.0でListenし、Application Serviceからのリクエストを受けられるようにしています/healthzエンドポイントを用意し、ヘルスチェックに使えるようにしていますpath.normalize+startsWithでディレクトリトラバーサル対策を入れています- 外部npmパッケージには依存せず、Node.js標準モジュールのみで構成しています
3. package.jsonを作成
続いてpackage.jsonを作成します。
{
"name": "elementary-report-app",
"version": "1.0.0",
"private": true,
"type": "module",
"engines": {
"node": ">=22"
},
"scripts": {
"start": "node server.mjs"
}
}
外部npmパッケージを使わない構成のため、npm installやnode_modulesは基本的に不要です。
4. app.ymlを作成
app.ymlは、App Runtimeのビルド・実行・パッケージングを定義するファイルです。
run:
command: [node, server.mjs]
artifacts:
- src: "server.mjs"
dest: "."
- src: "package.json"
dest: "."
- src: "public/index.html"
dest: "."
- src: "public/elementary_output.json"
dest: "."
profile:
label: "Elementary Report"
description: "Static hosting for Elementary report on Snowflake App Runtime"
ここでは以下を定義しています。
run.command: アプリ起動時に実行するコマンドartifacts: デプロイ対象に含めるファイル。server.mjsとpackage.json、public/配下のElementaryレポートを含めますprofile: アプリのラベルや説明
public/配下のファイルの配置先(dest)と、server.mjs側が参照するパスがズレていると、デプロイ後にElementaryレポートが404になってしまうので注意してください(原因の詳細は後述の「ハマったポイント」を参照してください)。
5. ローカルで動作確認
Snowflakeへデプロイする前に、server.mjsが想定どおりに動くかローカルで確認しておきます。
npm start
別ターミナルでヘルスチェックします。
curl http://localhost:8080/healthz
以下のように返ってくればOKです。
ok
ブラウザでhttp://localhost:8080を開き、Elementaryのレポート画面が表示されることを確認します。

確認できたら、Ctrl + Cでサーバーを停止します。
6. Snowflake側のオブジェクトを作成
検証用にDatabaseとWarehouseを作成します。SchemaはPUBLICを使います。
USE ROLE ACCOUNTADMIN;
CREATE DATABASE IF NOT EXISTS SAGARA_SNOWFLAKE_APPS;
CREATE WAREHOUSE IF NOT EXISTS SAGARA_SNOWFLAKE_APPS_QUERY_WH
WAREHOUSE_SIZE = XSMALL
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
Database作成時に通常PUBLICスキーマも作成されますが、念のため明示的に作成する場合は以下も実行します。
CREATE SCHEMA IF NOT EXISTS SAGARA_SNOWFLAKE_APPS.PUBLIC;
必要に応じて、アプリをデプロイするロールに権限を付与します。例としてSYSADMINロールでデプロイする場合は以下のとおりです。
USE ROLE ACCOUNTADMIN;
GRANT USAGE ON WAREHOUSE SAGARA_SNOWFLAKE_APPS_QUERY_WH TO ROLE SYSADMIN;
GRANT USAGE ON DATABASE SAGARA_SNOWFLAKE_APPS TO ROLE SYSADMIN;
GRANT USAGE ON SCHEMA SAGARA_SNOWFLAKE_APPS.PUBLIC TO ROLE SYSADMIN;
GRANT CREATE APPLICATION SERVICE ON SCHEMA SAGARA_SNOWFLAKE_APPS.PUBLIC TO ROLE SYSADMIN;
GRANT CREATE STAGE ON SCHEMA SAGARA_SNOWFLAKE_APPS.PUBLIC TO ROLE SYSADMIN;
7. Snowflake App Runtimeのセットアップ
App Runtime用の設定を作成します。デプロイ先を明示的に指定することで、個人用データベースへの配置を避けます。
snow app setup \
--app-name elementary_report_app \
--database SAGARA_SNOWFLAKE_APPS \
--schema PUBLIC \
--warehouse SAGARA_SNOWFLAKE_APPS_QUERY_WH
複数の接続を使い分けている場合は、接続名を指定します。
snow app setup \
--connection <connection_name> \
--app-name elementary_report_app \
--database SAGARA_SNOWFLAKE_APPS \
--schema PUBLIC \
--warehouse SAGARA_SNOWFLAKE_APPS_QUERY_WH
実行後、snowflake.ymlが自動生成されます。以下は私が実行した際に作られたファイルの内容です。

definition_version: "2"
entities:
elementary_report_app:
type: snowflake-app
identifier:
name: ELEMENTARY_REPORT_APP
database: SAGARA_SNOWFLAKE_APPS
schema: PUBLIC
artifacts:
- src: ./*
dest: ./
ignore:
- node_modules
- .env*
- __pycache__
- "*.pyc"
- .next
- .git
- snowflake.log
query_warehouse: SAGARA_SNOWFLAKE_APPS_QUERY_WH
code_stage: ELEMENTARY_REPORT_APP_CODE
database・schemaが個人用データベース(USER$<ユーザー名>のような形式)になっている場合は、チームへの共有ができません。--database・--schemaオプションを明示してsnow app setupを再実行してください。
8. デプロイ
snow app deployでSnowflakeへのアップロード・ビルド・デプロイを一括で実行します。
snow app deploy
接続名を明示する場合は以下のとおりです。
snow app deploy --connection <connection_name>
ログの表示が同じ箇所で止まっているように見えても、App ready at https://...のようなメッセージが表示されるまで待ちます。

数分後、下図のように表示されればデプロイ成功です。

9. アプリを開いてレポートを表示
デプロイが完了したら、snow app openでブラウザからアプリを開きます。
snow app open
接続名を明示する場合は以下のとおりです。
snow app open --connection <connection_name>
URLだけを表示したい場合は--print-onlyを付けます。今回私はWSL2のUbuntu 24.04 LTSで検証しているため、以下のコマンドを実行しました。
snow app open --print-only

このURLをブラウザに貼り付けてSnowflakeへの認証後、ブラウザでElementaryのレポートが表示されれば成功です。


10. 他のロールへの共有
チームメンバーに共有したい場合は、対象のロールにUSAGE権限を付与します。今回は例としてANALYSTロールに共有します。
USE ROLE ACCOUNTADMIN;
GRANT USAGE ON DATABASE SAGARA_SNOWFLAKE_APPS TO ROLE ANALYST;
GRANT USAGE ON SCHEMA SAGARA_SNOWFLAKE_APPS.PUBLIC TO ROLE ANALYST;
GRANT USAGE ON APPLICATION SERVICE
SAGARA_SNOWFLAKE_APPS.PUBLIC.ELEMENTARY_REPORT_APP
TO ROLE ANALYST;
これにより、ANALYSTロールを持つユーザーもSnowflakeの認証を経由してApp RuntimeのURLにアクセスできるようになります。
11. Application Serviceを確認
作成されたApplication Serviceは、SHOW SERVICESではなくSHOW APPLICATION SERVICESで確認します。
USE DATABASE SAGARA_SNOWFLAKE_APPS;
USE SCHEMA PUBLIC;
SHOW APPLICATION SERVICES;
対象のApplication Serviceだけを絞り込みたい場合は以下のとおりです。
SHOW APPLICATION SERVICES LIKE 'ELEMENTARY_REPORT_APP';
ELEMENTARY_REPORT_APPが表示されればOKです。

12. レポート更新時の流れ
Elementaryのレポートを再生成したら、public/配下のファイルを差し替えて再デプロイします。
dbtプロジェクトのルートから作業する場合は以下のとおりです。
cp edr_target/elementary_report.html elementary-report-app/public/index.html
cp edr_target/elementary_output.json elementary-report-app/public/elementary_output.json
cd elementary-report-app
snow app deploy
すでにelementary-report-appディレクトリにいる場合は以下のとおりです。
cp ../edr_target/elementary_report.html public/index.html
cp ../edr_target/elementary_output.json public/elementary_output.json
snow app deploy
内部的には新しいバージョンが作成され、Application Serviceの参照先が新バージョンへ切り替わることで、同じURLのまま最新のElementaryレポートを参照できるようになります。CI/CDパイプラインやdbtの実行後にこれらのコマンドを組み込んでおけば、レポートの自動更新もできそうです。
13. デプロイしたアプリを停止する
最後に、検証が終わったApp Runtimeのアプリを停止する方法も記載しておきます。
Snowflake App Runtimeでデプロイしたアプリは、Application Serviceとして起動しています。
不要になった場合は、snow app teardownでApplication Serviceを削除できます。
snow app teardown --connection <connection_name>
確認プロンプトを省略したい場合は、--forceを付けます。
snow app teardown --connection <connection_name> --force
このコマンドは、現在のプロジェクト定義、つまりelementary-report-appディレクトリ内のsnowflake.ymlをもとに、対象のApplication Serviceを削除します。
そのため、基本的にはsnowflake.ymlがあるディレクトリで実行します。
cd elementary-report-app
snow app teardown --connection <connection_name>
実際に実行すると下図のように表示されます。

削除後、以下のSQLでApplication Serviceが存在しないことを確認できます。
USE DATABASE SAGARA_SNOWFLAKE_APPS;
USE SCHEMA PUBLIC;
SHOW APPLICATION SERVICES LIKE 'ELEMENTARY_REPORT_APP';
ELEMENTARY_REPORT_APPが表示されなければ削除完了です。
なお、snow app teardownはApplication Serviceと関連するcode stage上のファイルを削除しますが、今回作成したDatabaseやWarehouseまでは削除しません。
検証用に作成したSnowflakeオブジェクトも不要であれば、別途以下のように削除します。
USE ROLE ACCOUNTADMIN;
DROP WAREHOUSE IF EXISTS SAGARA_SNOWFLAKE_APPS_QUERY_WH;
DROP DATABASE IF EXISTS SAGARA_SNOWFLAKE_APPS;
一度停止したアプリを再度起動したい場合は、同じプロジェクトディレクトリで再度デプロイすればOKです。
snow app deploy --connection <connection_name>
ハマったポイント:デプロイ後にURLを開いてもNot Foundになる
今回、snow app deploy自体は正常に完了し、App RuntimeのURLも発行されているにもかかわらず、ブラウザで開くとNot Foundと表示される事象に遭遇しました。
デプロイログ上では、以下のようにpublic/index.htmlやpublic/elementary_output.jsonはstageへアップロードされていました。
Uploaded public/elementary_output.json -> ...
Uploaded public/index.html -> ...
そのため最初は「ファイルはアップロードされているはずなのになぜ?」となったのですが、原因はstageへのアップロード後、App Runtimeの実行パッケージ内でNode.jsサーバーが参照しているパスにファイルが存在していなかったことでした。
当初はapp.ymlで以下のように指定していました。
artifacts:
- src: "public/**"
dest: "public"
一方で、server.mjs側ではpublic/index.htmlを参照する実装にしていました。
しかし、実行環境上で想定どおりの配置になっておらず、結果としてindex.htmlを見つけられずNot Foundになっていました。
最終的には、public/ディレクトリを実行パッケージ内で維持するのではなく、必要な静的ファイルをpackage rootに配置する形に変更しました。
artifacts:
- src: "server.mjs"
dest: "."
- src: "package.json"
dest: "."
- src: "public/index.html"
dest: "."
- src: "public/elementary_output.json"
dest: "."
あわせて、server.mjs側も実行パッケージrootをドキュメントルートとして扱うようにしました。
const documentRoot = __dirname;
これにより、App Runtime上では以下のような配置になり、URL直下でindex.htmlを正しく返せるようになりました。
/
├── server.mjs
├── package.json
├── index.html
└── elementary_output.json
今回のように、snow app deployが成功しているのに画面がNot Foundになる場合は、エンドポイント作成の問題ではなく、App Runtimeの実行環境上でのファイル配置と、アプリケーション側の参照パスがずれている可能性があります。
切り分け用に/healthzや、実行環境内のファイル一覧を返す簡単なデバッグエンドポイントを用意しておくと、原因を特定しやすかったです。
SPCS版・Databricks Apps版との比較
これまでに私が試した2つの構成と比較すると、以下のような違いがあります。
| 項目 | SPCS版 | Databricks Apps版 | App Runtime版(今回) |
|---|---|---|---|
| 静的ファイル配信 | Nginxコンテナ | Python http.server |
Node.jsの最小HTTPサーバー |
| Dockerfile | 必要 | 不要 | 不要 |
| Docker build | 必要 | 不要 | 不要 |
| Image Repository | 必要 | 不要 | 不要 |
| docker push | 必要 | 不要 | 不要 |
| Compute Pool | 自分で作成 | Databricks Apps用のCompute Sizeを選択 | App Runtime側のマネージドPoolに任せる |
| 共有方法 | SERVICE ROLEへのgrant | Databricks Apps側のCAN USE権限付与 |
Application ServiceへのUSAGEgrant |
SPCS版で必要だった以下の作業は、App Runtime版では不要になりました。
- Dockerfileの作成
- Nginxの設定
- Docker imageのビルド
- Snowflake Image Repositoryの作成
docker login/docker push- Compute Poolの作成
- service spec YAMLの作成
snow spcs service create/snow spcs service list-endpoints
代わりに必要になったのは以下のファイルとコマンドだけです、アプリケーションのファイルさえ出来ればすぐにデプロイしてSnowflakeアカウントのユーザーに共有することが可能なのがSnowflake App Runtimeの強みです!
server.mjspackage.jsonapp.ymlsnowflake.yml(snow app setupで生成)snow app setup/snow app deploy/snow app open
最後に
Snowflake App Runtimeを使って、ElementaryのレポートをDockerなしでホスティングする構成を試してみました。
SPCSに比べるとコンテナイメージ管理の手間を丸ごと省けるため、Elementaryレポートのような軽量な社内向けWeb配信であれば、Snowflake App Runtimeはかなり扱いやすい選択肢になりそうです。GAに向けて仕様が変わる可能性もあるので、引き続きウォッチしていきたいと思います!





