Skip to main content

Database

A Database is a managed Postgres database. v1 supports Postgres only; MySQL on the runtime lands in v1.1.

Quick example

import { Project, Database } from '@sprintsail/sdk';

export const app = new Project('orders');

export const db = new Database(app, 'orders', {
engine: 'postgres',
version: '16',
});

Usage in a handler (after binding):

import { db } from '../infra.js';

await db.query(
'INSERT INTO orders (id, amount) VALUES ($1, $2)',
[order.id, order.amount],
);

const rows = await db.query<{ id: string; amount: number }>(
'SELECT id, amount FROM orders WHERE status = $1',
['paid'],
);

Config

interface DatabaseConfig {
engine: 'postgres' | 'mysql'; // mysql runtime support: v1.1
version: string; // e.g. '16', '16.6'
size?: 'small' | 'medium' | 'large'; // AWS only; default 'small'
publiclyAccessible?: boolean; // AWS only; default false
}

Target mapping

TargetMaps toNotes
awsRDSDefault db.t4g.micro, 20 GB gp3, encrypted, single-AZ. Master credentials stored in Secrets Manager. Provision is async (~5–10 min to "available").
sprintsail-runtimeCloudNativePG ClusterOne CNPG Cluster per Database primitive. Default 1 instance, 1Gi PVC. Ready in ~15s on kind, longer on real clusters. App user + database created via CNPG bootstrap.initdb.

Runtime methods

db.query<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;

pg-style parameterised SQL ($1, $2). Returns an array of rows.

Connection pools are per-process and cached for the lifetime of the container. Cold-start–sensitive primitives (Function, API) get a fresh pool per invocation; long-running primitives (WebApp, Worker, CronJob) reuse it.

What sail migrate does

PathWhat happens
AWS → AWSManual pg_dump/pg_restore for now (stubbed). Provider provisions the destination RDS.
AWS → Sprintsail RuntimeAuto: an in-cluster Kubernetes Job runs `pg_dump
Runtime → RuntimeSame in-cluster Job, K8s source secret → K8s dest secret for creds.
Runtime → AWSPlanned.

Credentials

You never deal with credentials in your code — db.query() resolves them through the runtime adapter.

On AWS: master creds in Secrets Manager as {username,password} JSON. On Runtime: CNPG auto-creates <cluster>-app Secret with username/password keys.

If you need direct DB access (psql from your laptop, debugging), open the right port and SG/Ingress rule. The credentials Secret is yours to read.

Safety

sail destroy for a Database on AWS sets SkipFinalSnapshot: true and DeleteAutomatedBackups: true. This is a deliberate dev/test default — you lose backups. v1.1 will add a protected flag.