Dibbla Docs Get started Guides Workflows Changelog
Open Console
Tutorial · Build it

Stage 2 — Give it data

Create a managed Postgres database, bind it with one redeploy, and watch Lumen migrate and seed itself — then query the 54 seeded incidents directly.

Lumen is live but empty. This stage gives it a managed Postgres database. You create the database, redeploy once to pick up its connection string, and the app migrates and seeds itself on boot — the first-run banner disappears and there are incidents to read.

Say this to your code agent

Give Lumen a managed Postgres database and bind it.

Create a managed Dibbla Postgres database named "lumen_incidents" — org-wide
scope, not scoped to a single deployment, because a later worker will need it
too. Then redeploy the current app with --update so it picks up the injected
DATABASE_URL_LUMEN_INCIDENTS secret and migrates itself. When it is up, curl
/api/health and /api/incidents and report the total incident count.

What happens next

Hand that prompt to your code assistant and it takes over the mechanics. It creates a managed Postgres database in your org, then redeploys the app once so the platform injects the database’s connection string as a secret. There is no URL to copy anywhere — creating the database is what binds it.

On that redeploy the app boots, finds the connection string, runs its own migrations to build the schema, and seeds itself. You do not run any of this by hand; the app does it the first time it sees a database.

When the assistant reports back, the app has changed. Open it and the first-run banner is gone — the incident list is populated with fifty-four seeded incidents, and the health check now says the database is "connected" instead of "absent".

A code assistant is non-deterministic, so the exact commands it runs and the order it reports them may differ from one run to the next. That is fine — the end state is what matters: a database bound, the app migrated and seeded, and real incidents to read.

Under the hood the CLI & code behind this step — optional

1. Create the database

$dibbla db create lumen_incidents
Secret: DATABASE_URL_LUMEN_INCIDENTS (auto-created)
This is a global secret available to all deployments in your org.
It will be injected automatically on every deploy.

Creating a database also creates the secret that carries its connection string. You do not copy a URL anywhere — the platform injects it.

Scope is chosen at create time — and there is no separate link step

A bare dibbla db create makes an org-wide database whose secret every deployment in the org receives. Passing --deployment <alias> instead scopes both the database and its secret to a single app. Either way there is no separate link or bind command — the scope you pick at creation is the binding.

This tutorial uses the org-wide form deliberately: Stage 5 adds a nightly worker, which is a second deployment, and it needs the same database. Scope it to lumen now and that later worker could not reach it.

The secret is DATABASE_URL_<NAME>, never a bare DATABASE_URL

Here the name is lumen_incidents, so the secret is DATABASE_URL_LUMEN_INCIDENTS. This holds whatever the scope — there is no bare DATABASE_URL. Read the connection string from the _<NAME> variable in your app’s config.

2. Redeploy to pick it up

The secret is injected at deploy time, so the running app does not see it until you redeploy. Use --update to ship a new version of the existing app:

$dibbla deploy --update -m "chore: bind lumen_incidents"
deploy ok  ·  https://lumen-0ee1f995.dibbla.app  ·  3.2s

On boot the app finds DATABASE_URL_LUMEN_INCIDENTS, runs its migrations to create the schema, and seeds it.

3. Check it

The health check now reports the database as connected, and the incidents endpoint returns seeded rows in an {"items":[...],"total":N} envelope:

$curl https://lumen-0ee1f995.dibbla.app/api/health
{"app":"Lumen","database":"connected","status":"ok"}
$curl https://lumen-0ee1f995.dibbla.app/api/incidents
{"items":[ ... ],"total":54}

Fifty-four incidents were seeded. Open the app and the first-run banner is gone; the incident list is populated.

You can also connect to the database directly. dibbla db connect with -q prints just the connection string, so you can hand it straight to psql:

$psql "$(dibbla db connect lumen_incidents -q)"

The seed data is real enough to ask real questions of. Open incidents by region:

SELECT region, count(*)
FROM incidents
WHERE resolved_at IS NULL
GROUP BY region
ORDER BY 2 DESC;

region     | count
------------+-------
ap-south   |     5
us-east    |     5
eu-north   |     4
eu-central |     4
(18 open)

Recent high-severity incidents, joined to the service they hit:

SELECT i.title, s.name, i.opened_at
FROM incidents i
JOIN services s ON s.id = i.service_id
WHERE i.severity IN ('high', 'critical')
AND i.opened_at > now() - interval '30 days'
ORDER BY i.opened_at DESC;

-- returns several rows: recent high/critical incidents with their service

Mean time to resolution per region:

SELECT region, avg(resolved_at - opened_at) AS mttr
FROM incidents
WHERE resolved_at IS NOT NULL
GROUP BY region;

-- all four regions return a value

Next: data it can reason about

Lumen has fifty-four incidents, each with a free-text body nobody has time to read in full. Stage 3 adds an endpoint that summarises one with AI — using your Dibbla token as the model key.

Stage 3 → Give it AI

Also at this point

  • Managed storage — data has meant managed Postgres so far. Files are the other half of that sentence, and having just connected a database you may already be wondering where uploads would go. Lumen doesn’t need file storage to be the app it is, so this stays a pointer, not a step.