Lakebase as Graph DB — OntoBricks Reference
OntoBricks ships with one built-in graph database engine: Lakebase Postgres. This document covers everything you need to provision, configure, and operate…
OntoBricks ships with one built-in graph database engine: Lakebase Postgres. This document covers everything you need to provision, configure, and operate it — from the API gotchas that trip up fresh installs to the Postgres schema layout and troubleshooting runbook.
For the developer guide on adding a new engine, see docs/graphdb-integration.md.
Table of Contents
- Architecture overview
- Prerequisites
- Provisioning the Lakebase project
- Configuring the engine in the app
- Write modes
- Postgres schema layout
- Scripts reference
- Permissions bootstrap
- Knowledge Graph build — step by step
- Troubleshooting
1. Architecture overview
┌─────────────────────────────────────────────────┐
│ OntoBricks (FastAPI) │
│ │
│ GraphDBFactory.create(engine="lakebase") │
│ └─ LakebaseFlatStore │
│ │ │
│ │ COPY FROM STDIN / INSERT │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Lakebase Postgres (App-bound) │ │
│ │ schema: ontobricks_graph │ │
│ │ g_<domain>_v<n> (app_managed) │
│ │ g_<domain>_v<n>_sync (synced table) │
│ │ g_<domain>_v<n>__app (companion) │
│ │ g_<domain>_v<n> (UNION VIEW) │
│ └─────────────────────────────────────────┘ │
│ │ │
│ │ Lakeflow snapshot pipeline │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Unity Catalog │ │
│ │ <catalog>.<schema>.<domain>_vN_sync │ │
│ │ (registered synced table) │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
OntoBricks maintains two complementary storage layers:
| Layer | Technology | Purpose |
|---|---|---|
| Triple Store | Delta views in Unity Catalog (SQL Warehouse) | Governance, lineage, SPARQL source-of-truth |
| Graph DB | Lakebase Postgres (flat triple table or UNION view) | Fast in-process graph traversal, reasoning, cohort writes |
The Graph DB engine is selected per domain under Domain → Information → Knowledge Graph (defaults to lakebase). Engine connection settings remain workspace-global under Settings → Back end.
2. Prerequisites
2.1 — Databricks workspace requirements
| Requirement | Notes |
|---|---|
| Databricks Apps enabled | Needed to run OntoBricks as a platform app |
| SQL Warehouse | Standard or Serverless; bound as the sql-warehouse resource |
| Unity Catalog | A catalog + schema for the registry and triplestore views |
| Lakebase feature | Must be enabled on the workspace (contact workspace admin if absent) |
psql on PATH |
Required by scripts/bootstrap/lakebase-perms.sh (brew install libpq && brew link --force libpq on macOS) |
2.2 — Python dependencies
Lakebase support is an optional extra since v0.4.0:
# Local development
uv sync --frozen --extra lakebase
# Or pip
pip install ".[lakebase]"This installs psycopg[binary]>=3.2.0 and psycopg-pool>=3.2.0. The deployed app.yaml already includes --extra lakebase in the startup command.
2.3 — Critical API distinction
Lakebase has two project-creation APIs with different capabilities:
| API | Endpoint | Synced Tables compatible? |
|---|---|---|
| New (Autoscaling only) | POST /api/2.0/postgres/projects |
NO |
| Old (Autoscaling + Provisioned) | POST /api/2.0/database/instances |
YES |
The Databricks UI "New project" button calls the new API and produces a project that is incompatible with POST /api/2.0/database/synced_tables (used by the Knowledge Graph managed_synced build mode). Always use scripts/bootstrap/setup-lakebase.sh to provision the project.
3. Provisioning the Lakebase project
3.1 — Create with setup-lakebase.sh
Run once per workspace before the first deploy:
./scripts/bootstrap/setup-lakebase.sh --name ontobricks-demo --capacity CU_2The script:
- Checks whether the instance name already exists via
GET /api/2.0/database/instances. - Creates it via
POST /api/2.0/database/instances(synced-tables-compatible). - Polls until the instance reaches
AVAILABLE. - Resolves the branch endpoint and creates the Postgres database.
- Prints the
db-…resource id — copy this intoscripts/deploy.config.sh.
All options:
| Flag | Default | Description |
|---|---|---|
--name NAME |
ontobricks-demo |
Lakebase instance name |
--capacity CU_N |
CU_2 |
Compute tier: CU_1, CU_2, CU_4 |
--branch BRANCH |
production |
Initial branch name |
--database DBNAME |
ontobricks_demo |
Postgres datname to create |
--profile PROFILE |
DEFAULT |
Databricks CLI profile |
--wait N |
120 |
Seconds to wait for AVAILABLE |
--dry-run |
— | Print plan without executing |
3.1b — One-click provisioning from Settings (in-app alternative)
Admins can provision a graph DB end-to-end from the UI instead of running the two scripts by hand. In Settings → Lakebase → Connection tab there is a "Create graph DB from scratch" card: fill in the instance/project name, compute capacity, branch, Postgres database, graph schema, and the MCP app name, then click Create graph DB. The action runs as an async job (a progress bar + per-step log update live, polling GET /tasks/{id} like a Knowledge Graph build) and performs the same flow as scripts/bootstrap/setup-lakebase.sh + scripts/bootstrap/lakebase-perms.sh:
- Create the Lakebase instance (via the synced-tables-compatible
/api/2.0/database/instancesAPI) and wait forAVAILABLE. - Create the Postgres database and the graph schema.
- Grant
CAN_USEon the project andUSAGE/CREATE/DMLon the schema to the app and MCP service principals; optionally grantALL_PRIVILEGESon the configured UC catalog (managed-sync only).
On success the chosen project/branch/database/schema are written into graph_engine_config, so the Connection pickers reflect the new target.
Permission model (unchanged — only automated). The button runs as the app's own service principal, not a human. It therefore needs the SP to be allowed to create Lakebase instances; if it is not, the job fails on the first step with a clear message. Schema grants to the MCP SP are best-effort and surfaced as warnings when the MCP Postgres role does not exist yet. In those cases the shell scripts (
POST /api/2.0/database/instancesas a human owner) remain the documented fallback — re-runscripts/bootstrap/lakebase-perms.shafter the apps have connected once.
3.2 — After the script
Set the project + Postgres datname in scripts/deploy.config.sh (deploy.sh resolves the db-… segment automatically):
DEFAULT_LAKEBASE_PROJECT="<project-name>"
DEFAULT_LAKEBASE_DATABASE="<postgres-datname>"
# Optional override:
# LAKEBASE_DATABASE_RESOURCE_SEGMENT="db-xxxx-xxxxxxxxxx"You can also look it up at any time:
databricks postgres list-databases \
"projects/<project-name>/branches/production" -o json \
| python3 -c "import sys,json; [print(d['name']) for d in json.load(sys.stdin)]"3.3 — Name reservation gotcha
If you delete a Lakebase project from the new /postgres/projects API, the name may remain ghost-reserved in the /database/instances namespace for an extended period (15 minutes to hours). If setup-lakebase.sh fails with Instance name is not unique, choose a different name and update deploy.config.sh.
4. Configuring the engine in the app
4.1 — UI configuration
Go to Settings → Graph DB → Engine Configuration and enter a JSON object:
{
"schema": "ontobricks_graph", // Postgres schema for graph tables (default)
"database": "ontobricks_demo", // Postgres database (overrides PGDATABASE)
"sync_mode": "app_managed" // or "managed_synced" — see §5
}
The engine selector should show lakebase. If it shows empty, reload the page.
4.2 — All graph_engine_config.lakebase keys
graph_engine_config is nested per backend::
{
"lakebase": { ... keys below ... },
"neo4j": { "uri": "...", "database": "neo4j", ... },
"lakehouse": { "warehouse_id": "..." }
}
Flat legacy blobs are still accepted and rewritten to this shape on Save. Lakehouse SQL calls resolve lakehouse.warehouse_id (then fall back to the global warehouse).
| Key | Type | Default | Description |
|---|---|---|---|
schema |
string | ontobricks_graph |
Postgres schema for graph triple tables. Overridden by the Registry Volume schema when Settings → Registry resolves a non-empty triplet. |
database |
string | injected PGDATABASE |
Postgres database name — overrides the Apps-injected value. |
sync_mode |
string | app_managed |
Write mode: app_managed (direct COPY) or managed_synced (Lakeflow pipeline). |
sync_table_mode |
string | snapshot |
Lakeflow pipeline type: snapshot, triggered, or continuous. Only used in managed_synced. |
sync_timeout_s |
int | 600 |
Max seconds to wait for a Lakeflow sync run to complete. |
sync_uc_catalog |
string | (auto-detected) | UC catalog for synced table registration. Auto-detected from Registry settings / ONTOBRICKS_SYNC_UC_CATALOG / domain.delta.catalog. |
4.3 — Environment variables (deployed app)
The Apps runtime auto-injects these when the postgres resource is bound in databricks.yml:
| Variable | Source | Description |
|---|---|---|
PGHOST |
Apps runtime | Lakebase endpoint hostname |
PGPORT |
Apps runtime | Postgres port (5432) |
PGDATABASE |
Apps runtime | Postgres database name |
PGUSER |
Apps runtime | Postgres username (SP client ID in Apps) |
PGSSLMODE |
Apps runtime | SSL mode (require) |
The Postgres password is never stored. LakebaseAuth mints a short-lived JWT via POST /api/2.0/postgres/credentials on every connection open.
For local development (no Apps resource injection), set these in .env:
LAKEBASE_PROJECT=ontobricks-demo2 # Autoscaling project name
LAKEBASE_BRANCH=production # Branch to connect to
LAKEBASE_DATABASE=ontobricks_demo # Postgres datname
LAKEBASE_SCHEMA=ontobricks_registry # Registry schema
PGUSER=you@example.com # Your Databricks login email4.4 — deploy.config.sh variables
These drive the DAB deployment (edit before make deploy):
| Variable | Description |
|---|---|
DEFAULT_LAKEBASE_PROJECT |
Lakebase project name (final segment of projects/<id>) |
DEFAULT_LAKEBASE_BRANCH |
Branch (e.g. production) |
DEFAULT_LAKEBASE_DATABASE |
Postgres datname the registry schema lives in |
LAKEBASE_DATABASE_RESOURCE_SEGMENT |
Optional env override for the db-… id; when unset, deploy.sh resolves it from DEFAULT_LAKEBASE_DATABASE |
DEFAULT_LAKEBASE_SCHEMA |
Postgres schema for the registry (mirrors LAKEBASE_SCHEMA in app.yaml) |
deploy.config.shis registry-scoped. The graph DB schema/database are configured in-app (Settings → Graph DB→graph_engine_config) and may live in a different Lakebase project — they are not deploy vars.
5. Write modes
5.1 — app_managed (default)
The FastAPI process streams R2RML rows from the SQL Warehouse and writes them directly into the *_sync table via COPY FROM STDIN. The same 3-object layout used by managed_synced is created: a *_sync bulk-data table, a *__app companion for reasoning/cohort writes, and a union view for readers.
R2RML view (SQL Warehouse)
│ iter_rows batches
▼
LakebaseFlatStore.bulk_load_into_sync
│ COPY FROM STDIN → g_<domain>_v<n>_sync (app-owned)
▼
g_<domain>_v<n> (UNION VIEW over _sync + __app)
- Simple setup — no Lakeflow pipelines required.
- App process is on the hot path for large graphs.
- Reasoning / cohort writes always go to
*__app(consistent withmanaged_synced). - Suitable for most use cases.
5.2 — managed_synced (Lakeflow)
A Databricks Lakeflow snapshot pipeline keeps a Postgres synced table in lock-step with the R2RML Delta view. The app only orchestrates; bulk movement happens entirely on the Databricks side.
R2RML view (Unity Catalog)
│ Lakeflow snapshot pipeline
▼
g_<domain>_v<n>_sync (Postgres, Lakeflow-owned, read-only)
App writes (reasoning, cohort):
g_<domain>_v<n>__app (Postgres, app-owned, writable)
Readers:
g_<domain>_v<n> (UNION VIEW over _sync + __app)
Enable it with:
{ "sync_mode": "managed_synced" }When to use managed_synced:
- Source tables are very large (millions of triples).
- You want Databricks lineage on the synced table.
- The app process should not be the bottleneck during builds.
Additional requirements for managed_synced:
- The Lakebase project must be provisioned via
scripts/bootstrap/setup-lakebase.sh(provisioned instance, not autoscaling-only) — see §2.3. - The app SP needs
CAN_USEon the Lakebase database instance — applied byscripts/bootstrap/lakebase-perms.sh. - The UC schema for the synced table must exist before the first build (
CREATE SCHEMA IF NOT EXISTSis run automatically by the build pipeline).
6. Postgres schema layout
6.1 — Schemas
OntoBricks uses up to three Postgres schemas in the same Lakebase project:
| Schema | Default name | Created by | Purpose |
|---|---|---|---|
| Registry | ontobricks_registry |
Settings → Registry → Initialize |
Project metadata, domain configs, schedule runs |
| Graph DB | ontobricks_graph |
First Knowledge Graph Build | Per-domain triple tables (and views in managed_synced) |
| Sync | (UC registry schema segment) | First Lakeflow snapshot | Auto-created by Lakeflow; mirrors the UC <schema> segment |
6.2 — Objects per graph version
Both app_managed and managed_synced use the same 3-object layout per domain version. The difference is who writes to the *_sync table.
| Object | Owner | Naming | Description |
|---|---|---|---|
| Sync table | App (app_managed) / Lakeflow (managed_synced) |
g_<domain>_v<n>_sync |
Bulk warehouse data; (subject, predicate, object, datatype, lang). App writes via COPY FROM STDIN; Lakeflow writes via snapshot pipeline. |
| Companion table | App (read/write) | g_<domain>_v<n>__app |
Reasoning / cohort / materialise triples; (subject, predicate, object, datatype, lang) |
| UNION view | App DDL | g_<domain>_v<n> |
SELECT … FROM _sync UNION ALL SELECT … FROM __app; exposes the back-compat 5-column shape |
All SPARQL queries and graph traversal operations target the back-compat name g_<domain>_v<n> — no downstream code is aware of which mode is active.
6.3 — Drop cascade (both modes)
LakebaseFlatStore.drop_table(name) removes all three objects in order:
DROP VIEW IF EXISTS g_<domain>_v<n>(UNION view)DROP TABLE IF EXISTS g_<domain>_v<n>__app(companion)app_managed:DROP TABLE IF EXISTS g_<domain>_v<n>_sync(sync table)managed_synced:SyncedTableManager.delete(uc_name, purge_data=True)— removes the UC synced-table registration and the underlying Postgres_synctable
6.4 — Long literal objects (object_hash)
Postgres btree indexes (including the composite primary key) cannot index TEXT values longer than ~2704 bytes. OntoBricks therefore stores the full object literal for reads/deletes but keys uniqueness on a generated object_hash column (digest(object, 'sha256') via the pgcrypto extension).
pgcrypto must live in public. Pooled connections run SET search_path TO "<graph_schema>", public, and a bare CREATE EXTENSION installs into the first search_path entry — i.e. the graph schema. Since IF NOT EXISTS is then a permanent no-op, changing the graph schema strands digest() out of reach and every Build fails with function digest(text, unknown) does not exist.
Two places keep this correct, both idempotent:
ensure_pgcrypto(app) installs intopublicand relocates a stranded extension viaALTER EXTENSION pgcrypto SET SCHEMA public. The app owns any extension it created, so it can self-heal.make bootstrap-lakebaseStep 1b does the same as the admin, and warns (without aborting) when the extension is app-owned and cannot be relocated.
The extension is per database — the graph database is often a different Lakebase project/database from the registry (graph_engine_config.database), so fixing one does not fix the other.
app_managed:*_syncand*__apptables are created withPRIMARY KEY (subject, predicate, object_hash).managed_synced: the Delta warehouse VIEW exposesobject_hash(sha2(object, 256)) and Lakeflow usesprimary_key_columns = [subject, predicate, object_hash].
Graphs created before this layout need a full Knowledge Graph rebuild (drop
- recreate) to pick up the new schema.
7. Scripts reference
scripts/bootstrap/setup-lakebase.sh
Provisions a Lakebase project via POST /api/2.0/database/instances (synced-tables-compatible).
# Basic usage
./scripts/bootstrap/setup-lakebase.sh --name my-project --capacity CU_2
# Dry-run to preview
./scripts/bootstrap/setup-lakebase.sh --name my-project --dry-run
# Custom profile
./scripts/bootstrap/setup-lakebase.sh --name my-project --profile prod-workspaceOutputs: prints the db-… resource id (informational). Set DEFAULT_LAKEBASE_PROJECT / DEFAULT_LAKEBASE_DATABASE in deploy.config.sh; optional override LAKEBASE_DATABASE_RESOURCE_SEGMENT.
scripts/bootstrap/lakebase-perms.sh
Grants the app service principals the Postgres and control-plane permissions they need to operate. Idempotent — safe to run repeatedly.
# Registry schema
scripts/bootstrap/lakebase-perms.sh \
-i ontobricks-demo2 -b production \
-d ontobricks_demo -s ontobricks_registry \
-a ontobricks-030 -a mcp-ontobricks
# Graph DB schema (run after first Build)
scripts/bootstrap/lakebase-perms.sh \
-i ontobricks-demo2 -b production \
-d ontobricks_demo -s ontobricks_graph \
-a ontobricks-030 -a mcp-ontobricks
# Sync schema (managed_synced only — run after first Lakeflow snapshot)
scripts/bootstrap/lakebase-perms.sh \
-i ontobricks-demo2 -b production \
-d ontobricks_demo -s ontobricks \
-a ontobricks-030 -a mcp-ontobricksmake deploy (via scripts/deploy.sh) grants the registry schema automatically. The graph and sync schemas are granted by the in-app "Create graph DB" flow or by running the commands above manually — they are not deploy vars, since the graph DB may live in a different Lakebase project.
What each run grants:
| Grant | Level | Purpose |
|---|---|---|
CREATE EXTENSION pgcrypto WITH SCHEMA public |
Database | Installs / relocates digest() for companion object_hash (Step 1b) |
CAN_USE (control-plane) |
Lakebase instance | Allows the SP to call Lakebase APIs (e.g. synced_tables) |
CAN_USE (autoscaling API) |
Lakebase project | Belt-and-suspenders for autoscaling path |
USAGE + CREATE |
Postgres schema | Let the SP create tables/views in the schema |
SELECT/INSERT/UPDATE/DELETE |
All existing tables | DML on current objects |
USAGE/SELECT/UPDATE |
All existing sequences | Required for bigserial PKs |
ALTER DEFAULT PRIVILEGES |
Schema | Future tables/sequences inherit the same grants |
ALL PRIVILEGES (UC catalog) |
Unity Catalog catalog | Read back synced tables; only granted when -c flag passed |
scripts/deploy.sh
Full deploy pipeline (called by make deploy). On the dev-lakebase target it:
- Renders
app.yamlfromapp.yaml.template+deploy.config.sh. - Validates the DAB bundle.
- Deploys both apps.
- Starts the main app.
- Bootstraps app self-permissions (
bootstrap-app-permissions.sh). - Runs
bootstrap-lakebase-perms.shfor all configured schemas.
make deploy # dev-lakebase target (default)
make bootstrap-lakebase # run only the Lakebase grants
make deploy-volume # dev target (volume-only, no Lakebase binding)8. Permissions bootstrap
8.1 — Order of operations
Lakebase schemas are created lazily (by app actions), so grants must follow creation:
Step 1: make deploy
→ CAN_USE on instance applied immediately (before schema exists)
Step 2: Open app → Settings → Registry → Initialize
→ Creates 'ontobricks_registry' schema in Postgres
Step 3: make bootstrap-lakebase (or make deploy again — idempotent)
→ Applies USAGE + DML on 'ontobricks_registry' schema
Step 4: Build a Knowledge Graph (Settings → Knowledge Graph → Build)
→ Creates 'ontobricks_graph' schema (first build)
Step 5: make bootstrap-lakebase (or make deploy again)
→ Applies USAGE + DML on 'ontobricks_graph' schema
Step 6: (managed_synced only) First Lakeflow snapshot completes
→ Creates the sync schema automatically
Step 7: make bootstrap-lakebase (or make deploy again)
→ Applies USAGE + DML on sync schema
make deploy is always safe to re-run — it skips schemas that don't exist yet and prints an informational message instead of failing.
8.2 — Verify permissions
Check what the SP has been granted from a SQL editor or psql:
-- From psql (connected as human admin)
\dn+ -- list schemas + ACLs
\dp ontobricks_graph.* -- table-level ACLs
SELECT * FROM information_schema.role_table_grants WHERE grantee = '<sp-client-id>';Check CAN_USE on the instance (Databricks CLI):
databricks permissions get database-instances/<instance-id> -o json9. Knowledge Graph build — step by step
This section describes what the Lakebase engine does during a Build for the managed_synced mode. For app_managed, steps 3–6 are replaced by direct COPY FROM STDIN ingestion.
| Step | What happens | What can fail |
|---|---|---|
| 1 | Resolve the synced UC FQN: <catalog>.<schema>.<domain>_vN_sync |
Wrong catalog resolved — check sync_uc_catalog / ONTOBRICKS_SYNC_UC_CATALOG |
| 2 | CREATE SCHEMA IF NOT EXISTS in Unity Catalog (SQL Warehouse DDL) |
SP missing CREATE SCHEMA on UC — grant via SQL |
| 3 | SyncedTableManager.ensure(...) — idempotent create_synced_database_table call |
Database instance is not found — project created via wrong API; Not authorized — SP missing CAN_USE on instance |
| 4 | Create companion table g_<domain>_vN__app in Postgres |
SP missing CREATE on graph schema |
| 5 | SyncedTableManager.trigger_and_wait(...) — fires Lakeflow snapshot, waits for completion |
Timeout — increase sync_timeout_s; pipeline stuck — check Lakeflow pipeline status in Databricks UI |
| 6 | LakebaseFlatStore.ensure_synced_union_view(name) — creates the UNION view |
"<view>" is not a view — an old table with the same name exists (auto-dropped since v0.4.1); _sync table not found — Lakeflow didn't materialise the table yet |
| 7 | TRUNCATE companion (full rebuild only) |
Build logs are streamed to the UI and to the application log. Look for lines tagged [DT-BUILD <id>] for per-step context.
10. Troubleshooting
Database instance is not found
Failed to create synced table …: Database instance is not found.
Cause: The Lakebase project was created via the new autoscaling API (/postgres/projects) which is not listed in /database/instances. The Synced Tables API only accepts provisioned instance names.
Fix:
- Delete the old project from the UI.
- Re-create it with
scripts/bootstrap/setup-lakebase.sh. - Update
DEFAULT_LAKEBASE_PROJECT/DEFAULT_LAKEBASE_DATABASEindeploy.config.sh(optional:LAKEBASE_DATABASE_RESOURCE_SEGMENT). make deploy.
If the name is reserved (Instance name is not unique), choose a different name — deleted names can stay ghost-reserved for hours.
The user is not authorized … assign 'Can Use' or 'Can Manage'
Failed to create synced table …:
The user is not authorized … assign cf06ae08… 'Can Use' or 'Can Manage'
for Database instance 6b981581-…
Cause: The app service principal lacks CAN_USE on the Lakebase instance.
Fix:
make bootstrap-lakebase
# or manually:
databricks permissions update database-instances/<instance-id> \
--json '{"access_control_list":[{"service_principal_name":"<sp-id>","permission_level":"CAN_USE"}]}'"<view>" is not a view
Failed: Could not create Lakebase union view after sync: "<name>" is not a view.
Cause: An object with the union view's name already exists as a TABLE (e.g. left over from an app_managed build on the same version). CREATE OR REPLACE VIEW cannot replace an existing table in PostgreSQL.
Fix (automatic since v0.4.1): The ensure_union_view function now auto-detects and drops the conflicting table before creating the view. If you see this error on an older deployment, drop the table manually:
-- From psql connected to the Lakebase database
DROP TABLE IF EXISTS ontobricks_graph."g_<domain>_vN" CASCADE;Then retry the build.
_sync table '…_b' not found in Postgres
Failed: Could not create Lakebase union view after sync:
_sync table 'cust360auto_v4_sync_b' not found in Postgres.
Cause: The Lakeflow snapshot pipeline ran against the wrong branch (e.g. production instead of demo). The _sync table therefore landed in a different Lakebase branch schema.
Fix:
- In Settings → Graph DB, verify
databasematches the Postgresdatnamefor your branch. - In
deploy.config.sh, verifyDEFAULT_LAKEBASE_BRANCHpoints to the branch configured in the app settings. make deployand rebuild.
Lakebase connection failed: database "ontobricks_registry" does not exist
Cause: The registry database or schema has not been created yet. This is expected on a fresh deployment.
Fix (in order):
- Open the deployed app.
- Go to Settings → Registry → Initialize.
- After initialisation, run
make bootstrap-lakebase(ormake deploy).
logicalDatabaseName must be defined when creating synced table in a standard catalog
Cause: The graph_engine_config.database key is missing or the PGDATABASE env var was not injected by the Apps runtime (postgres resource not bound).
Fix:
- Confirm the
postgresresource binding in the Databricks Apps UI. - Add
"database": "<datname>"to thegraph_engine_configJSON. - Restart the app.
Must specify either database instance name or both database project and branch
Cause: The synced table registration call is missing both the instance name and the project+branch pair. This means lakebase_project or lakebase_database_resource_segment is empty in deploy.config.sh.
Fix:
- Confirm
DEFAULT_LAKEBASE_PROJECT/DEFAULT_LAKEBASE_DATABASEindeploy.config.sh. - If auto-resolve fails, set
LAKEBASE_DATABASE_RESOURCE_SEGMENT=db-xxxx-xxxxxxxxxx(fromdatabricks postgres list-databases "projects/<project>/branches/<branch>" -o json). make deploy.
Build uses app_managed even though managed_synced is configured in Settings
Symptom: The build log shows sync_mode=app_managed and iterates triples through the app process. The Settings → Graph DB page correctly displays the saved config with "sync_mode": "managed_synced".
Cause (fixed in v0.6.0): On cold start, if the Lakebase store was briefly unavailable (typical the first few seconds after the app container started), the GlobalConfigService in-memory cache was populated with the empty template (_empty()). Subsequent reads within the 5-minute cache TTL returned the empty config, so the build resolved sync_mode as missing and silently fell back to app_managed. The Settings page was not affected because it always forces a fresh read.
Fix: Upgrade to v0.6.0 — _resolve_lakebase_mode now bypasses the cache via force=True. No configuration change needed; simply redeploy.
Settings → Graph DB: catalog list is empty
The UC catalog dropdown uses the configured SQL Warehouse. If the warehouse is not yet saved to the global config, the dropdown falls back to DATABRICKS_SQL_WAREHOUSE_ID from the environment. If all fallbacks fail, the "Configure a SQL warehouse first" message appears.
Fix:
- Go to Settings → Databricks and save the SQL Warehouse.
- If it still fails, verify
DATABRICKS_SQL_WAREHOUSE_ID/DATABRICKS_SQL_WAREHOUSE_ID_DEFAULTare set in the Apps resource binding or.env.
Delete asset button does nothing (Settings → Graph DB)
Cause: window.confirm() is suppressed inside the Databricks Apps iframe.
Fix (applied since v0.4.1): The delete flow uses a Bootstrap modal instead of window.confirm(). If you see this on an older deployment, make deploy to pick up the fix.
Quick-start checklist (Lakebase Graph DB)
[ ] 1. Create Lakebase project:
./scripts/bootstrap/setup-lakebase.sh --name <name> --capacity CU_2
[ ] 2. Set DEFAULT_LAKEBASE_PROJECT / DEFAULT_LAKEBASE_DATABASE in deploy.config.sh
(optional override: LAKEBASE_DATABASE_RESOURCE_SEGMENT="db-xxxx-xxxxxxxxxx")
[ ] 3. Set DEFAULT_LAKEBASE_BRANCH (and DEFAULT_LAKEBASE_SCHEMA if needed) in deploy.config.sh
[ ] 4. make deploy
[ ] 5. Bind resources in Databricks Apps UI (sql-warehouse, volume, postgres)
[ ] 6. Open app → Settings → Registry → Initialize
[ ] 7. make bootstrap-lakebase (or make deploy — idempotent)
[ ] 8. Open Settings → Graph DB
- Engine: lakebase
- Config: { "sync_mode": "app_managed" } (or "managed_synced")
[ ] 9. Build your first Knowledge Graph
[ ] 10. make bootstrap-lakebase again (grants on ontobricks_graph schema)