Database
elements man database Read as markdownThe 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.