Operating your app
Once an app is live, you need to look inside it and fix things: correct a row, run a query, see why a job failed, rotate a key, undo a mistake. You can do all of it on the development or production database, from the builder's Backend panel or by asking your coding agent. Every production change is backed up first and recorded.
When to use it
- A customer asks you to fix their booking, or a row was entered wrong.
- You want an answer the screens don't give ("which classes are always full?").
- A workflow failed and you want to see why, then run it again.
- You need an index, a view or a table the contract doesn't describe.
From the builder: the Backend panel
Open the project and the Backend panel. The Dev / Prod switch at the top picks the database. On Prod the panel turns amber, every change asks for confirmation, and production is backed up before each change.
| Pane | What you do there |
|---|---|
| Data | Browse any table, edit or add rows in a table editor. Writes go through the app's rules |
| SQL | Run any SQL: several statements in one transaction, reads and writes |
| Schema | Everything in the database: tables, columns, keys, indexes, views, functions, triggers, policies, and which ones the contract manages |
| Backups | Database snapshots with Restore, and deploy history with Roll back |
| Workflows | Run now with a JSON input on dev or prod, and Failed jobs with Replay |
| Logs | Workflow runs and their log lines, notifications, payments, files |
| Live | Change events and topic messages as they happen, and recent requests and errors |
| Secrets | Environment variables and secrets for dev, prod or both. Values are never shown again |
| Users, Auth | Your app's accounts, roles and sign-in settings |
From your agent
The same operations are MCP tools (and CLI commands and HTTP routes). Each takes env: "dev" (default) or "prod". Ask in plain words: "on prod, set the capacity of Tuesday's Sunrise Flow to 20".
| Tool | CLI | What it does |
|---|---|---|
sql | appbricx sql "…" | Any SQL as the database admin. A read-only script runs rolled back. Up to 1,000 rows back |
edit_rows | appbricx rows update session --id … --patch … | Insert, update or delete through the app's data API: access, rules, lifecycles and workflows behave as in the app. as a role to act as a user |
describe_schema | appbricx schema | The real schema, each table marked contract, platform, internal or hand-made |
snapshots | appbricx snapshots | List, take or restore database snapshots |
deploys | appbricx deploys | Deploy history and rollback |
run | appbricx run workflow <id> | Run a workflow now, read a run, list and replay failed jobs |
tail | appbricx tail events --since 15m | Recent change events, topic messages, requests or errors |
secrets | appbricx secrets set NAME - | List names (never values), set or delete secrets |
A real production edit and its undo
On the tutorial's booking app, an agent changed a class on prod:
edit_rows { "table": "session", "env": "prod", "op": "update",
"id": "852eddbb-…", "patch": { "capacity": 20 } }
→ { "succeeded": 1, "failed": 0,
"snapshotId": "prod-20261012T101217397Z-001-agent-editrows" }The change shows up as a live event, then the snapshot taken before it puts it back:
tail { "kind": "events", "env": "prod", "since": "3h" }
→ { "table": "session", "op": "update", "payload": { "title": "Sunrise Flow", "capacity": 20, … } }
snapshots { "action": "restore", "env": "prod", "id": "prod-20261012T101217397Z-001-agent-editrows" }
→ { "restored": "prod-20261012T101217397Z-001-agent-editrows",
"undoSnapshotId": "prod-20261012T101228236Z-003-prerollback" }
sql { "env": "prod", "sql": "select title, capacity from session where id = '852eddbb-…'" }
→ { "rows": [{ "title": "Sunrise Flow", "capacity": 14 }], "readOnly": true }Your own SQL: indexes, views, extra tables
You can change the development database by hand: add indexes, views, functions, triggers, constraints, policies, extra columns or whole tables. Appbricx keeps them.
- Apply never drops or rewrites them. If a contract change would break one (for example a
SELECT *view on a table whose text fields change), the apply fails, names it, and runs nothing. List the view's columns instead of*. - Publish carries them to production in dependency order: indexes, views, materialized views, functions, triggers, sequences, enum types, constraints and policies. A change that needs a DROP waits for a destructive publish.
- A table you made gets row-level security with no policies, so only admin access reads it, until you adopt it.
Adopt a hand-made table into the app
sql { "sql": "create table supplier (id uuid primary key default gen_random_uuid(), name text not null, email text)" }
patch_contract [{ "op": "adopt_table", "table": "supplier", "personas": ["instructor"],
"access": { "instructor": { "read": "all", "create": true, "update": "all", "delete": "all" } } }]Its columns become fields (text, number, boolean, date, timestamp, enums, and refs for uuid foreign keys to app tables). The table and its rows are kept. It needs a single-column primary key named id.
Secrets
Keys your server code needs (a weather API key, a webhook signing secret) live in Backend, Secrets or the secrets tool, never in code. Server functions and workflows read them with await ctx.secrets.get("NAME"). Setting and deleting secrets needs a workspace owner or admin.
Gotchas
- Prefer
edit_rowsover SQL for data. SQL writes go past access and rules and don't fire workflows;edit_rowsbehaves like the app. - Keep contract names under the contract. Rename or retype contract tables and fields with
patch_contract, notALTER. - Scopes matter. Reads need read; dev writes and secrets need apply; prod writes, restores and rollbacks need deploy. Choose them when you authorize an agent.
- Every write is audited with who made it, which tool and which environment (never a secret value).
- Rapid edits share a snapshot. Prod edits within a few minutes of each other reuse one snapshot instead of filling the 30-snapshot history.
- Don't touch
_appbricx_*tables: they are internal.