Manual Database

Database

elements man database Read as markdown

The database is a core part of the Elements story. A full-stack web application is fundamentally a system for moving data between users and a database, and Elements treats the database accordingly. Migrations, real-time channels, cron, and background jobs are built into Elements directly on top of the database, not added as separate services. That deep integration is what makes building a full-stack web app quick.

The database is Postgres. Postgres, formally PostgreSQL, is an open-source relational database. Data is organized into tables with typed columns, and queries are written in SQL. Standardizing on a single database lets Elements deliver a consistent set of examples and packages that work for every project. Postgres is great for getting started and will scale with your application indefinitely.

Postgres Is Bundled

You do not install Postgres. Elements bundles Postgres 18.4 and manages it for you.

A per-machine background daemon (elements-machine) runs a single Postgres cluster shared by every Elements project on the machine. The cluster is created automatically on first use, kept healthy (self-healing), and configured for loopback-only trust authentication. It listens on port 5433 (not the usual 5432), so it never collides with a Postgres you may already run. In development its data directory is ~/elements/db.

On the first build, your project connects to the daemon, the cluster is ensured ready, and two databases are created for the project automatically: the app database and a test database. Their names derive from the project directory name, normalized (for example MyApp becomes my_app and my_app_test), or from database.name in config.jsoc.

There is nothing to start, nothing to install, and no connection string to paste. A freshly created app builds and runs with a working database out of the box.

Configure

The database block in config.jsoc supplies connection values. Every field is optional; empty or omitted fields fall back to the bundled cluster defaults (host 127.0.0.1, port 5433, user postgres, no password).

// config.jsoc
{
  database: {
    name: "my_app",
    host: env("DB_HOST", "127.0.0.1"),
    port: env<number>("DB_PORT", 5433),
    user: env("DB_USER", "postgres"),
    password: env("DB_PASSWORD", ""),
  },
}
# config/env/development.env
DB_HOST=localhost

A wrong-typed value fails the build before the project server tries to connect.

To use a database other than the bundled cluster, a remote or hosted Postgres, set DB_HOST (and the other DB_* values) to that server. When host points somewhere other than the local cluster, Elements connects there and leaves the bundled cluster out of the picture entirely. See Remote and Hosted Postgres.

App and Test Databases

Elements provisions two databases per environment: an app database and a test database. The app database holds the application's data. Every build's tests run against the test database, leaving the app database untouched.

Tests automatically route to the test database. Route handlers, @rpc functions, jobs, and cron all run against the app database. Elements picks the right database based on the calling context, so there is no flag to flip per query.

Tests are not a separate environment. They run as part of the build in every environment (development, production, staging), against that environment's test database. If you want a dedicated environment for pre-production verification, configure a staging environment.

The default database names are <app> and <app>_test, derived from your project name. Override the app database name under database.name in config.jsoc; the test database always tracks <name>_test.

Elements maintains two schemas in every database. Application tables live on the public schema. Elements-internal tables, including the migrations table and the background jobs queue, live on a separate elements schema. This keeps Elements' bookkeeping out of the way of your own tables and reuses Postgres's own namespacing instead of inventing a prefix convention.