marina.db is a managed PostgreSQL database for data owned by your app.
It is separate from a workspace Connection to an existing data source. Marina
creates the database when the service is approved; no setup is required.
Your organization has one managed Postgres deployment, shared by its apps.
Each app receives its own isolated schema inside it: an app can never read,
change, or list another app’s data, and redeploying an app keeps its data.
Enable the database
Declare the versioned service inmarina.json:
marina.json
Create the schema with migrations
Runtime code cannot run DDL. Put ordered SQL files in the flatmarina/migrations directory instead:
marina/migrations/001_create_expenses.sql
marina/migrations/002_add_category.sql
- Validates the exact migration sequence in an isolated test database.
- Applies deterministic safety rules.
- Adds data and operational risks to the deployment approval plan.
Write expand-compatible migrations
A migration may finish before the new version becomes live, so it must remain compatible with the currently live version. Prefer this sequence:- Expand: add nullable columns, new tables, or other compatible structures.
- Deploy: update the app to tolerate both the old and new shape.
- Backfill: move large, bounded data rewrites out of deployment DDL.
- Contract later: remove old structures only through an explicitly reviewed maintenance operation, not a deployment migration.
NOT NULL, privilege or ownership
changes, dynamic DO blocks, and attempts to override Marina’s role, search
path, timeouts, or transaction. Data rewrites, immediate constraint validation,
and potentially blocking index builds require explicit review.
Do not include BEGIN, COMMIT, ROLLBACK, savepoints, or prepared transaction
commands. Marina owns the transaction boundary.
Query from the app
Use positional parameters for every value. Never interpolate request data into SQL text:src/app.js
{ rows, rowCount }. Values crossing the runtime boundary
are JSON-compatible. Timestamps are represented as ISO strings, large integers
and exact numerics can be strings, and binary values are represented as
{ $bytes: "<base64>" }.
The private app schema isolates applications, not users within one app. Put the authenticated user
or tenant in the data model and include it in every relevant query predicate.
Run an atomic transaction
Pass a bounded list of parameterized statements when they must all commit or all roll back:Runtime limits and query guidelines
Use explicit column lists, predicates, and
limit clauses. Paginate large
reads and keep long-running backfills out of request handlers. Runtime access
allows table SELECT, INSERT, UPDATE, and DELETE plus sequence use; it
does not allow schema creation or DDL.
Handle conflicts and availability
Runtime failures have the nameMarinaRuntimeError, a stable code, and a
retryable hint:
retryable is true. Do not expose
raw SQL, parameters, or database errors in an HTTP response or application log.