Codemation Docs
Configuration

Persistence

Configure database persistence—SQLite or PostgreSQL—paths, URLs, and migrations.

… stars

This page covers app.database: where the host stores application data (runs, users, credentials metadata, and related records).

It is not about file or blob storage (S3, uploads, attachments). Those are usually workflow or node concerns, not this config surface.

It also covers the storage backing for framework observability data such as traces, span artifacts, and metric points. Codemation stores those in the same database engine as the rest of the host state.

Codemation supports two database modes for consumer apps:

  • sqlite for embedded local development
  • postgresql for shared environments and production

Local default: SQLite

SQLite is the shortest path to a working app on one machine.

Example:

app: {
  database: {
    kind: "sqlite",
    sqliteFilePath: ".codemation/codemation.sqlite",
  },
}

This is a good default when:

  • you are learning Codemation
  • one developer is iterating locally
  • you do not need multiple processes or shared access yet

sqliteFilePath is where the local database file lives on disk; it is still database persistence, not a general-purpose file store. Paths resolve relative to the consumer project root unless you pass an absolute path.

If you omit sqliteFilePath, Codemation falls back to .codemation/codemation.sqlite.

Shared environments: PostgreSQL

Switch to PostgreSQL when the app needs a shared database.

Example:

app: {
  database: {
    kind: "postgresql",
    url: process.env.DATABASE_URL,
  },
}

The URL must be a postgresql:// or postgres:// connection string.

Typical environment setup:

DATABASE_URL=postgresql://user:password@127.0.0.1:5432/codemation

After pointing the app at PostgreSQL, run migrations:

pnpm exec codemation db migrate

A practical starter pattern

The generated templates switch between local SQLite and PostgreSQL based on REDIS_URL and DATABASE_URL:

const useRedisRuntime = Boolean(process.env.REDIS_URL);
const databaseUrl = process.env.DATABASE_URL?.trim();

if (useRedisRuntime && (!databaseUrl || databaseUrl.length === 0)) {
  throw new Error(
    "DATABASE_URL is required when REDIS_URL is set (BullMQ requires a shared PostgreSQL database).",
  );
}

app: {
  database: useRedisRuntime
    ? { kind: "postgresql", url: databaseUrl! }
    : { kind: "sqlite", sqliteFilePath: ".codemation/codemation.sqlite" },
}

That gives one simple progression:

  1. local SQLite while you are building
  2. PostgreSQL when the app becomes shared
  3. PostgreSQL plus Redis when you add queue-backed workers

Run retention vs telemetry retention

Run persistence and telemetry retention are related, but they are not the same policy.

You can configure the runtime so:

  • debugger-friendly run state expires quickly
  • telemetry spans and artifacts live longer for incident review
  • aggregate metric points live longest for dashboards and usage trends

That separation works in both SQLite and PostgreSQL, so you can keep local development simple without designing yourself into a corner for production.

The host-level defaults come from environment variables:

  • CODEMATION_RUN_RETENTION_DEFAULT_SECONDS
  • CODEMATION_BINARY_RETENTION_DEFAULT_SECONDS
  • CODEMATION_TELEMETRY_SPAN_RETENTION_DEFAULT_SECONDS
  • CODEMATION_TELEMETRY_ARTIFACT_RETENTION_DEFAULT_SECONDS
  • CODEMATION_TELEMETRY_METRIC_RETENTION_DEFAULT_SECONDS

Workflows can still override the defaults with their own prune policy when a specific automation needs different retention windows.

Environment overrides

The host also supports environment-level overrides for database kind and paths:

  • DATABASE_URL for PostgreSQL URLs
  • CODEMATION_DATABASE_KIND to force postgresql or sqlite
  • CODEMATION_SQLITE_FILE_PATH to override the local SQLite database file path

These are useful when the same codebase needs different persistence in local, staging, and production environments.

BullMQ compatibility rule

If you move to queue-backed scheduling, do not keep SQLite.

BullMQ requires:

  • Redis for queues
  • PostgreSQL for shared persistence

That means this combination is valid:

REDIS_URL=redis://127.0.0.1:6379
DATABASE_URL=postgresql://user:password@127.0.0.1:5432/codemation

This combination is not:

  • Redis queues with local SQLite only

app.database vs runtime.database

Most consumer apps should configure persistence through app.database.

Use runtime.database only when you need the lower-level runtime shape directly. The consumer-facing app form is the recommended path for templates and normal apps.

  1. Configuration
  2. Engine
  3. Deployment

On this page