Skip to content
AbloAblo Docs
Esc
navigateopen⌘Jpreview
On this page

Operating on Your Database

Which actions are read-only, which writes need a guard, and which changes belong to a human.

Ablo sits over your database as a coordination layer, not an owner. It reads your Postgres replication stream and routes model writes into your own tables. The hosted service does not run application DDL, migrations, or drops. That boundary keeps model operations attributable while your migration tool remains responsible for the database shape.

The habit that makes it easy is to look before you act. One command shows you the real shape of your database measured against your schema, and changes nothing:

npx ablo check   # read-only — reports which columns fit your models and which don't

When a question is about the live database — does this column exist, is it nullable, will this write fit — you can usually answer it by observing rather than reasoning in the dark.

The floor: what Ablo never does

These hold on every database Ablo connects to, and they are what bound the blast radius of anything you do through the model API:

  • It never runs DDL or migrations on your database, and never drops a table or column. Schema changes to your own tables are always your application’s action, run with your admin credential — never Ablo’s.
  • It never owns your rows. Canonical data stays in your tables; Ablo hosts only the transaction log and the coordination state.
  • Every model write is checked against active claims and recorded. A plain write is last-write-wins when no claim applies. A functional update, held claim, or explicit readAt guard protects a write that depends on an earlier value.

Ablo prevents a non-holder from writing through another participant’s claim by default. It does not infer that every plain update is a read-modify-write operation; use the guarded forms when lost-update protection matters.

Direct SQL remains outside that enforcement path. If an existing application service writes the same row directly, keep its database constraints and locks as the final integrity boundary and route every participating caller through one named operation. Ablo can select one worker before expensive work begins; the existing service must still re-read, validate, and commit authoritatively. See Coordinate an existing database operation.

Three kinds of action

Sort any action you’re about to take into one of these, and the right move follows.

Normal application operations. Reads (get, list), ablo check, and ablo pull observe and never change anything. Previews — --show-sql, --dry-run — print the exact SQL a command would run without executing it. Model writes through ablo.<model>.create / update are authorized, checked against active claims, optimistic locally, rolled back locally if the server rejects them, and recorded. Review their data effects as you would any application write.

Verify first — needs one look at the live database. Routing an existing table’s writes through a model requires the model to match the table’s real columns. Run ablo check: it names the columns that fit and the ones that don’t, so a NOT NULL column your model doesn’t set shows up as a line in the report rather than a surprise at commit time. Decide the model shape from what check tells you, then proceed. Nothing here is risky — it just reads better after you’ve seen the ground truth.

Hand to a human — database administration. Raw DDL on the live database — ALTER TABLE … OWNER TO, adding or dropping a column, changing a constraint — changes the database itself, so it belongs to a person with their hand on it. So does a connect cutover run with its confirmation skipped (--yes): the prompt exists because the step provisions real roles and reconciles publication on a live database, and on a shared or production database that confirmation is the human’s to give. Removing a model from your pushed schema also deserves review because clients will lose that typed API surface.

The one action that isn’t what it looks like

Deleting a model from ablo/schema.ts removes it from the API contract the next time you push the schema. Existing clients can no longer access that model through Ablo. It does not drop the underlying table or its rows; database DDL remains your migration tool’s responsibility. Review client usage first, then remove the model and push the schema as a normal application change.

The verification loop

Most of the uncertainty in working on a live database dissolves into a few read-only checks:

  • ablo check — does the live database match the schema? Reports the exact column-by-column fit. Read-only.
  • ablo pull — what is actually in the database, expressed as a schema. Read-only, like prisma db pull.
  • --show-sql / --dry-run on connect and migrate — the exact statements, printed and unexecuted, so you approve the SQL before it runs.
  • Read the row and its claim state before you write — get / list, and ablo.<model>.claim.state({ id }) for who is already working on it.

The pattern underneath all of it is steady: observe first, use guarded writes when a change depends on prior state, and review DDL and cutovers separately because they change the database itself.

See also

Was this page helpful?