Features · Database
A real database, already wired.
Managed Postgres on the paid plan, with no database account to open: one database is included for your apps. Ask for it when you deploy, and one action creates it, connects it and only then builds — so your app goes live with its own tables in place.
Take my restaurant app live, with a database.
tofu · setFramework nextjs
confirmed
tofu · deploy database: true
managed database ready · Postgres
DATABASE_URL + 5 more · write-only
build ready
HTTP 200 · publicly reachable
Live at https://franks-kitchen-3f9a1c07b2e4.trytofu.app
One action
Create, connect, then build. In that order, in one step.
Choose a database on the deploy step — a checkbox in the dashboard, database: true from your agent, deploy --database from a shell. It costs money every hour it runs, so it is never a default: only your yes, for that app, creates one.
Create the database
A Postgres database of its own, in the region you choose: Americas, EMEA or APAC.Wait until it is healthy
For up to 2 minutes. If it is not connected by then, no build is submitted, and the answer names the state it is in.Write the connection settings
Onto your app’s hosting project, as write-only values. On a first deploy, Tofu creates that project here.Build, with the database there
Only now. Your migration runs against the new database in the very first build, and the app goes live with its tables.
A database created earlier from the Database page is connected the same way by your next deploy, before that deploy builds.
What your app receives
Wired in, never shown.
Tofu writes the connection settings straight into your hosting provider’s sensitive, write-only environment. Tofu itself keeps the names and nothing else, and no service-role key is used.
| Variable | Who receives it |
|---|---|
| DATABASE_URL | Every app — the connection string, through the provider’s transaction pooler. |
| SUPABASE_URL | Every app — the database project’s public address. |
| SUPABASE_ANON_KEY | Every app — its public key. |
| ‹prefix›SUPABASE_URL‹prefix›SUPABASE_ANON_KEY‹prefix›SUPABASE_PUBLISHABLE_KEY | Next.js (NEXT_PUBLIC_), Vite (VITE_) and Astro (PUBLIC_) apps — the public address and key again, under the name their browser bundle reads. |
Every other preset — a Python, Go or JavaScript server app included — gets the server-side names only, because Tofu does not guess a browser prefix.
Confirm your app’s framework before the database connects: the browser names are chosen from it at that moment, and are not added afterwards.
Your migrations, run by your build.
The database starts empty on purpose: the schema belongs to the repository that defines it. Put your migration in the build command and every deploy brings its schema along — no credential is copied anywhere, and the schema cannot fall behind the code it shipped with.
A migration that fails fails the build, and the previous version keeps serving. Statements it had already applied stay applied.
Structure travels; data does not. Your migration files reach this database. Rows that live only on your machine do not, unless a migration inserts them.
{
"scripts": {
"build": "prisma migrate deploy && next build"
}
}drizzle-kit migrate. Supabase CLI: supabase db push --db-url "$DATABASE_URL". Plain SQL: the runner your repository already has.See your data
A table editor, not a SQL console.
The Database page lists the tables in your public schema and pages through their rows — without handing anyone a console.
Read
Every public table, 25 rows a page
With each column’s type, the primary key and whether row-level security is on. A row count is the planner’s estimate, and says so.
Write
Off until you switch it on
Writing is a switch per app. Each insert, change or delete is then one row, confirmed on its own — and a row that changed meanwhile is reported, not overwritten.
Never
No schema changes, no SQL, no export
The editor cannot create, alter or drop anything, and rows leave it one page at a time, on your screen.
Yours alone
In your dashboard, not your agent
No agent can read or write rows. The editor connects as the database’s own admin role, so row-level security does not limit it — and the panel says so.
Yours to keep
Your data, and your way out.
Moved to your own Supabase organization
On request, the database moves to a Supabase organization you own — a transfer arranged with you and reviewed, in the same region, rather than a button.
The connection string, when you need it
For a local tool or a one-off data fix, Show the connection string rebuilds it for you, the owner, and records that it did. No agent can receive it.
Deleted when you say so
Deleting a database is an owner’s action: you type the app’s name, and the database, its schema and its data are removed, with no copy kept by Tofu.
Limits
What is not here yet
What a managed database on Tofu does not do, said as plainly as what it does.
Tofu runs no migrations, and has no SQL console. That is policy: uploaded source is untrusted input, and one operator credential spans every managed database.
Local data stays local. Rows that exist only on your machine never reach this database unless a migration inserts them.
No tables or policies of Tofu’s own. The database starts empty; your migrations create the tables, and the row-level-security policies your app relies on.
One database per app, on a paid plan. What the plan includes is on the pricing.
No password rotation. Nothing in the dashboard changes the database password; a suspected leak is a support case.
Browser names for Next.js, Vite and Astro only. Other presets get the server-side names, and no Python or Go app has been run against a managed database end to end yet.
Paste one line. Go live.
Your app, its database, your domain and your sign-in — from the agent you already use, in about 10 minutes.
The ship-it layer for vibe-coded apps. Your agent wrote it — Tofu ships it.
Works in all coding agents
© 2026 Tofu
trytofu.ai