Skip to main content
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 in marina.json:
marina.json
Database-backed deployments can require approval for the capability, managed resources, and migrations. Provisioning and migration happen only after a publisher approves the exact immutable artifact and its deployment plan.

Create the schema with migrations

Runtime code cannot run DDL. Put ordered SQL files in the flat marina/migrations directory instead:
marina/migrations/001_create_expenses.sql
marina/migrations/002_add_category.sql
Marina applies files in lexical filename order. Each file runs atomically, and Marina records each applied file’s name and checksum. Never edit, rename, remove, or reorder an applied migration; add a new file for the next change. An unchanged deployment is a no-op, while changed or missing history is rejected. Before a deployment can be approved, Marina:
  1. Validates the exact migration sequence in an isolated test database.
  2. Applies deterministic safety rules.
  3. Adds data and operational risks to the deployment approval plan.
Automated analysis cannot override a safety blocker. Marina applies only the migrations contained in the approved app version.

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:
  1. Expand: add nullable columns, new tables, or other compatible structures.
  2. Deploy: update the app to tolerate both the old and new shape.
  3. Backfill: move large, bounded data rewrites out of deployment DDL.
  4. Contract later: remove old structures only through an explicitly reviewed maintenance operation, not a deployment migration.
Deployment migrations block destructive changes such as drops, truncation, renames, column type changes, immediate 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
Each call returns { 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:
Interactive transaction callbacks are intentionally unavailable. Do not make network calls between transaction statements; compute the complete list first.

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 name MarinaRuntimeError, a stable code, and a retryable hint:
Use bounded exponential backoff only when retryable is true. Do not expose raw SQL, parameters, or database errors in an HTTP response or application log.

Data lifecycle and restores

The schema belongs to the app identity, not one artifact version. Redeploying, renaming, or archiving the app keeps its data. Deleting an app does not automatically drop its schema; database destruction requires a separate explicit data-deletion workflow. Marina does not run down migrations. A version can be restored only when the database schema revision recorded on that version exactly matches the app’s current revision. After any migration changes the revision, Marina refuses a restore of an older revision. Deploy new code that is compatible with the current schema instead.