はじめに
Databricks AppKitは、Databricks Apps上でWebアプリケーションを構築するためのTypeScript SDKです。
Databricks AppsはDatabricksワークスペース上でWebアプリをホスティング・実行するためのプラットフォーム機能で、従来はPython(Streamlit、Gradio、Flask、Dash)でアプリを構築するのが主流でした。AppKitはここにTypeScriptのフルスタック開発という新しい選択肢を加えるもので、SQL WarehouseやLakebase、AI/BI Genieといった各種Databricksサービスとの接続をプラグインとして提供し、型安全なデータ取得からReact UIコンポーネントまでを一つのフレームワークでカバーします。
整理すると以下の関係です。
- Databricks Apps = アプリを動かす「場所」(プラットフォーム)
- AppKit = アプリを作る「道具」(TypeScript SDK)
前回の記事ではAppKit・AI Dev Kit・aitools MCPの3つのツールの全体像と使い分けを整理しました。今回はAppKitにフォーカスし、アーキテクチャ、プラグインシステム、型安全なクエリなど、内部構造を掘り下げます。
AppKitの公式ドキュメントは以下にあります。
注意: AppKitは現在早期開発フェーズ(プレビュー段階)であり、APIは予告なく変更される可能性があります。本番環境での使用は非推奨です。
アーキテクチャ
Databricks Appsはアプリを動かすためのコンテナ環境(認証、ネットワーク、リバースプロキシ)を提供します。AppKitはその中で動くアプリケーション自体を構築するSDKであり、アプリのサーバーサイド(Node.js)とフロントエンド(React)の両方を担います。Streamlitで作ったアプリもStreamlit自体がサーバー+UIを持ってDatabricks Apps上で動きますが、それと同じ構造です。
AppKitは2つのnpmパッケージで構成されています。
@databricks/appkitはバックエンド側のコアSDKです。プラグインシステムのライフサイクル管理、テレメトリ、キャッシュ管理、ストリーミング、SQLクエリの型生成機能を提供します。
@databricks/appkit-uiはフロントエンド側のReact UIライブラリです。クエリ実行用のReactフック、Radix UIとTailwindベースのUIコンポーネント、データ可視化コンポーネントを含みます。
アプリケーション全体は3つの層で構成されます。
クライアント層はReactフロントエンドです。@databricks/appkit-uiが提供するチャートやテーブルなどのコンポーネントを使ってUIを構築します。サーバー層とはHTTPおよびSSE(Server-Sent Events)で通信します。
サーバー層はNode.jsバックエンドです。@databricks/appkitの各プラグインがここで動作し、SQL Warehouseへのクエリ実行、認証・認可、キャッシュ・リトライ・エラーハンドリングを処理します。開発時にはViteのホットリロード、本番では静的ファイルの配信も行います。
データ層はDatabricksサービスそのものです。分析クエリを実行するSQL Warehouse、アプリのデータを保存するLakebase(PostgreSQL互換)、ファイルを管理するUnity Catalog Volumes、自然言語クエリを処理するGenieスペースなどがここに該当します。
プラグインシステム
プラグインとは
AppKitにおけるプラグインとは、アプリとDatabricksの各サービスを接続するためのモジュールです。
例えば「SQL Warehouseにクエリを投げてデータを取りたい」ならAnalyticsプラグイン、「ユーザーが自然言語で質問できるチャットUIを付けたい」ならGenieプラグイン、というように、アプリに必要な機能に応じてプラグインを選んで組み合わせます。
各プラグインには以下が含まれています。
- Databricksサービスへの接続・認証処理
- サーバー側のAPIエンドポイント(
/api/<プラグイン名>/...に自動マウント) - フロントエンド向けのReactフック・コンポーネント
- キャッシュ、リトライ、テレメトリなどの本番向け機能
プラグインの登録
createApp()でAppKitインスタンスを生成する際に、使いたいプラグインを配列で渡します。
import { createApp, server, analytics, genie, files } from "@databricks/appkit";
const AppKit = await createApp({
plugins: [
server({ port: 8000 }),
analytics(),
genie(),
files(),
],
});
初期化フェーズ
プラグインは3つのフェーズで順番に初期化されます。
Coreフェーズはテレメトリやキャッシュなどフレームワーク内部の基盤が初期化されます。NormalフェーズではAnalytics、Genie、Files、Lakebaseといったアプリ向けプラグインが初期化され、それぞれAPIルートを登録します。DeferredフェーズではServerプラグインが、Normalフェーズで登録されたすべてのルートをまとめてExpressにマウントし、HTTPサーバーを起動します。
つまりServerプラグインが最後に初期化されるのは、他のプラグインが登録するルート(例: /api/analytics/...、/api/genie/...)を集約する必要があるためです。
組み込みプラグイン一覧
AppKitには6つの組み込みプラグインがあります。それぞれの役割を整理します。
| プラグイン | 一言で言うと | 接続先 |
|---|---|---|
| Server | アプリのHTTPサーバーを起動する | (Express + Vite) |
| Analytics | SQL Warehouseでデータを取得する | SQL Warehouse |
| Genie | 自然言語でデータに質問するチャットUIを提供する | Genieスペース |
| Lakebase | アプリのデータをPostgreSQLに保存する | Lakebase |
| Files | Unity Catalog Volumeのファイルを操作する | UC Volumes |
| Execution Context | クエリを誰の権限で実行するか制御する | (認証基盤) |
以下、各プラグインの詳細を見ていきます。
Serverプラグイン: アプリのHTTPサーバー
すべてのAppKitアプリに必須のプラグインです。Express + Viteベースのサーバーを起動し、他のプラグインが登録したAPIルートの配信と、フロントエンドの配信を行います。開発モードではViteのHMR(ホットリロード)が有効になり、本番ではビルド済みの静的ファイルを自動検出して配信します。
ヘルスチェック用の/healthエンドポイントも自動で追加されます。
最小構成は以下の通りです。
import { createApp, server } from "@databricks/appkit";
await createApp({
plugins: [server()],
});
Expressにカスタムルートを追加したい場合は、autoStart: falseで起動を遅延させます。
const appkit = await createApp({
plugins: [server({ autoStart: false })],
});
appkit.server.extend((app) => {
app.get("/custom", (_req, res) => res.json({ ok: true }));
});
await appkit.server.start();
Analyticsプラグイン: SQL Warehouseでデータを取得
AppKitの中核的なプラグインです。「SQLファイルを書く → 型が自動生成される → フロントエンドから型安全にデータを取得する」という一連の流れを実現します。
SQLファイルはconfig/queries/ディレクトリに配置します。ファイル名がそのままクエリキーになります(例: spend_summary.sql → "spend_summary")。
SQLファイル内では:paramNameプレースホルダーとコメントによる型アノテーションが使えます。
-- @param startDate DATE
-- @param endDate DATE
-- @param limit NUMERIC
SELECT *
FROM spend_data
WHERE usage_date BETWEEN :startDate AND :endDate
LIMIT :limit
対応するパラメータ型はSTRING、NUMERIC、BOOLEAN、DATE、TIMESTAMP、BINARYです。
実行コンテキストの切り替えはファイル名で行います。queryKey.sqlはサービスプリンシパル(アプリの権限)で実行され共有キャッシュが使われます。queryKey.obo.sqlはリクエストしたユーザー本人の権限(On-Behalf-Of)で実行され、ユーザーごとにキャッシュが分かれます。
Genieプラグイン: 自然言語でデータに質問
Databricks AI/BI GenieスペースをAppKitアプリに埋め込むプラグインです。エンドユーザーがSQLを書かずに、自然言語でデータに対して質問できるチャットUIを提供します。
複数のGenieスペースをエイリアス名で管理でき、SSEストリーミングによるリアルタイムのステータス更新や会話履歴のリプレイもサポートしています。
genie({
spaces: {
sales: "01ABCDEF12345678",
support: "01GHIJKL87654321",
},
});
フロントエンド側では<GenieChat>コンポーネントを配置するだけでチャットUIが完成します。
import { GenieChat } from "@databricks/appkit-ui/react";
function GeniePage() {
return (
<div style={{ height: 600 }}>
<GenieChat alias="sales" />
</div>
);
}
独自のチャットUIを構築したい場合はuseGenieChatフックを使います。
Lakebaseプラグイン: アプリのデータを保存
Databricks Lakebase(PostgreSQL互換のOLTPデータベース)への接続プールを提供するプラグインです。AnalyticsプラグインがSQL Warehouseで読み取りを担うのに対し、LakebaseプラグインはアプリケーションのCRUD操作(ユーザー情報の保存、注文データの永続化など)を担います。
OAuthトークンの自動リフレッシュ(1時間トークン、2分前にリフレッシュ)やトークンキャッシュ、OpenTelemetryインストルメンテーションが組み込まれています。
const AppKit = await createApp({
plugins: [server(), lakebase()],
});
// テーブル作成
await AppKit.lakebase.query(`CREATE TABLE IF NOT EXISTS app.orders (
id SERIAL PRIMARY KEY,
user_id VARCHAR(255) NOT NULL,
amount DECIMAL(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)`);
// データ取得
const result = await AppKit.lakebase.query(
"SELECT * FROM app.orders WHERE user_id = $1",
[userId],
);
// ORM用の設定も取得可能
const ormConfig = AppKit.lakebase.getOrmConfig();
標準のpg.Pool互換なので、既存のPostgreSQLライブラリやORMとそのまま組み合わせて使えます。
Filesプラグイン: ファイルの操作
Unity Catalog Volumeに対するファイル操作(一覧、読み取り、ダウンロード、アップロード、削除、プレビュー)を提供するプラグインです。ユーザーがアプリ上でファイルをアップロード・ダウンロードするような機能を実装する際に使います。
複数のVolumeを名前付きで定義でき、環境変数DATABRICKS_VOLUME_*からの自動検出にも対応しています。
# .envまたはapp.yamlで設定
DATABRICKS_VOLUME_UPLOADS=/Volumes/catalog/schema/uploads
DATABRICKS_VOLUME_EXPORTS=/Volumes/catalog/schema/exports
// ユーザーの権限(OBO)でファイル操作(推奨)
const entries = await appkit.files("uploads").asUser(req).list();
const content = await appkit.files("exports").asUser(req).read("report.csv");
フロントエンドではDirectoryList、FileBreadcrumb、FilePreviewPanelなどのコンポーネントでファイルブラウザを構築できます。
Execution Contextプラグイン: 実行権限の制御
クエリを「アプリの権限(サービスプリンシパル)」で実行するか「リクエストしたユーザー本人の権限(OBO)」で実行するかを管理するプラグインです。Analyticsプラグインと連携し、SQLファイル名の.obo.sqlサフィックスに基づいて実行コンテキストを自動で切り替えます。
型安全なSQLクエリ
AppKitの特徴的な機能の一つが、SQLファイルからTypeScriptの型を自動生成する仕組みです。
仕組み
型生成の流れは以下の通りです。
-
config/queries/フォルダ内の.sqlファイルをスキャン - SQLのパラメータアノテーション(例:
-- @param startDate DATE)を解析 - Databricks SQL Warehouseに接続して結果カラムの型を推論
- クエリパラメータと結果行のTypeScriptインターフェースを生成
- 型安全なクエリ実行のための
QueryRegistry型を作成
ポイントは手順3です。実際にSQL Warehouseへ接続してスキーマを取得するため、テーブル定義と完全に一致した型が生成されます。
Viteプラグインによる自動生成
開発時にはViteプラグインが.sqlファイルの変更を監視し、型を自動再生成します。
// client/vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { appKitTypesPlugin } from "@databricks/appkit";
export default defineConfig({
plugins: [
react(),
appKitTypesPlugin({
outFile: "src/appKitTypes.d.ts",
watchFolders: ["../config/queries"],
}),
],
});
なお、AppKitのdevサーバー経由でフロントエンドを配信している場合は、appKitTypesPlugin()が内部的に組み込まれているため、vite buildを別途実行する場合にのみVite設定への追加が必要です。
CLIによる手動生成
CI/CDパイプラインや手動生成にはCLIコマンドを使います。
npx @databricks/appkit generate-types . client/src/appKitTypes.d.ts
フロントエンドでの利用
型が生成されると、IDEによる補完と型チェックが効くようになります。
import { useAnalyticsQuery } from "@databricks/appkit-ui/react";
import { sql } from "@databricks/appkit-ui/js";
const { data } = useAnalyticsQuery("users_list", {
status: sql.string("active"),
limit: sql.number(50),
});
// TypeScriptが結果行の型を知っている
data?.forEach(row => {
console.log(row.email); // 補完が効く
});
パラメータは必ずuseMemoでラップしてください。フックはパラメータの参照が変わるたびに再実行されるため、useMemoなしでは無限リフェッチが発生します。
// OK
const params = useMemo(() => ({ status: sql.string("active") }), []);
const { data } = useAnalyticsQuery("users", params);
// NG - レンダーのたびに新しいオブジェクトが生成され、無限リフェッチが発生
const { data } = useAnalyticsQuery("users", { status: sql.string("active") });
UIコンポーネント
@databricks/appkit-uiにはデータアプリケーション向けのReactコンポーネントが含まれています。
データ可視化コンポーネントとしてAreaChart、BarChart、LineChart、PieChart、DonutChart、HeatmapChart、RadarChart、ScatterChart、DataTableがあります。
UIプリミティブとしてButton、Card、Dialog、Sidebar、Tabs、Table、Alert、Badge、Input、Select、Checkbox、Calendar、Toaster、Tooltipなど約60種類のコンポーネントがRadix UIとTailwindベースで提供されています。
Genie連携コンポーネントとして前述のGenieChatとuseGenieChatフックがあります。
ファイル管理コンポーネントとしてDirectoryList、FileBreadcrumb、FilePreviewPanelがあります。
設定
app.yaml
Databricks Appsへのデプロイ時の設定はapp.yamlで行います。
command:
- node
- build/index.mjs
env:
- name: DATABRICKS_WAREHOUSE_ID
valueFrom: sql-warehouse
commandでアプリの起動方法を指定し、envセクションでSQL WarehouseのIDなどの環境変数をバインドします。valueFrom: sql-warehouseはDatabricks Appsランタイムが設定済みのWarehouse IDを注入するディレクティブです。
ローカル開発時の認証
ローカル開発にはいくつかの認証方法があります。推奨はDatabricks CLI認証です。
databricks auth login --host <host> --profile DEFAULT
npm run dev
DEFAULTプロファイルを使っていればそのままnpm run devで起動できます。別のプロファイルを使う場合は環境変数で指定します。
DATABRICKS_CONFIG_PROFILE=my-profile npm run dev
.envファイルによる設定も可能です(.gitignoreに追加してください)。
DATABRICKS_HOST=https://xxx.cloud.databricks.com
DATABRICKS_TOKEN=dapi...
DATABRICKS_WAREHOUSE_ID=abc123...
開発フロー
AppKitは3つの開発フローをサポートしています。
ローカル開発はnpm run devでUI・バックエンド両方のホットリロードが有効な開発サーバーを起動します。ほとんどのユースケースで推奨される方法です。
AI支援開発はAgent Skillsを使って、AIコーディングアシスタントにデータ探索やCLIコマンド実行、アプリのスキャフォールドを任せる方法です。databricks experimental aitools skills installでセットアップします。
Remote Bridgeはデプロイ済みのバックエンドに対して、クエリとUIだけをローカルで開発するモードです。本番データに対するテストやデプロイ済みバックエンドのデバッグに有用です。
カスタムプラグインの作成
組み込みプラグインでカバーできないロジックが必要な場合は、カスタムプラグインを作成できます。CLIでスキャフォールドを生成できます。
npx @databricks/appkit plugin create
Pluginクラスを継承してtoPlugin()でエクスポートする形です。
import { Plugin, toPlugin, type PluginManifest } from "@databricks/appkit";
class MyPlugin extends Plugin {
static manifest = {
name: "myPlugin",
displayName: "My Plugin",
description: "カスタムプラグイン",
resources: { required: [], optional: [] }
} satisfies PluginManifest<"myPlugin">;
async setup() {
// 初期化処理
}
myMethod() {
return { message: "Hello from custom plugin" };
}
exports() {
return { myMethod: this.myMethod };
}
}
export const myPlugin = toPlugin(MyPlugin);
ルート追加にはinjectRoutes()、ライフサイクル管理にはsetup()とshutdown()、共有サービスにはthis.cache(キャッシュ)やthis.telemetry(テレメトリ)を使います。
設計原則
AppKitは7つの設計原則に基づいています。
- Highly opinionated: ベストプラクティスに基づく強いデフォルトを提供
- Built for application use cases: インフラ管理ではなくアプリ開発のためのSDK
- Delightful developer experience: プラグアンドプレイな開発体験
- Zero-trust security: 最小限の露出面、安全なデフォルト、全入力のバリデーション
- Optimized for humans and AI: 人間とLLMの両方が使えるAPI設計
- Production-ready from day one: 可観測性、信頼性、スケーラビリティを初日から
- Layered extensibility: 高レベルプラグイン、低レベルプリミティブ、カスタムプラグイン用の拡張ポイント
特に5番目の「人間とAI両方への最適化」は特徴的で、llms.txtやCLAUDE.mdの同梱、npx @databricks/appkit docsによるドキュメント提供など、AIコーディングアシスタントとの協調を前提とした設計が随所に見られます。
まとめ
AppKitは単なるWebフレームワークではなく、Databricksサービスとの統合を前提に設計されたフルスタックアプリケーションSDKです。プラグインという形でSQL Warehouse、Lakebase、Genie、Unity Catalog Volumesへの接続を必要に応じて組み合わせ、型安全なデータ取得からUIコンポーネントまで一気通貫で開発できます。
まだプレビュー段階ですが、Databricks Apps上での本格的なTypeScriptアプリ開発の方向性を示すSDKとして注目に値します。



