Your first sqlrs workflow
sqlrs makes experiments against reproducible SQL database states easier. Instead of preparing a
shared database by hand, you describe a recipe. Local can prepare an immutable state from that
recipe and create isolated, mutable instances for development, tests, and migration checks.
The four objects to know
Section titled “The four objects to know”| Object | Meaning |
|---|---|
| Workspace | A project directory containing local .sqlrs/ configuration. It bounds the files a recipe may use. |
| Prepare recipe | A command and its SQL files, psql includes, or Liquibase changelogs. It must fully describe the database you need. |
| State | The immutable result of a prepare recipe. Local can reuse it while the image, arguments, and input files remain unchanged. |
| Instance | A mutable database derived from a state. Tests and applications change the instance without changing the state or another instance. |
The repository stores migrations, SQL, and a short description of how to execute them. Prepared states remain derived local data. Local materializes them when needed, reuses a matching result, and manages them within its cache.
Initialize a workspace
Section titled “Initialize a workspace”Install the archive for your platform, start its documented container runtime, and open a terminal in a learning project:
sqlrs init local --snapshot auto
sqlrs status
A ready setup reports status: ok, a local profile and mode, the current workspace, and an
available container runtime. Endpoint and cache values depend on the machine.
Create a state and an instance
Section titled “Create a state and an instance”sqlrs prepare:psql --image postgres:16 -- -c "create table if not exists smoke_check(id int); insert into smoke_check values (1);"
A successful prepare prints DSN=postgres://…. Everything after DSN= is the connection string for
the new mutable instance. Do not commit it. Arguments after -- belong to psql; sqlrs uses the
image, normalized arguments, and input content when identifying the prepared state.
Inspect both sides of the model:
sqlrs ls --states
sqlrs ls --instances
Run the same prepare command again. Because the recipe did not change, Local can reuse its prepared state while returning a new mutable instance. Changes in one instance do not reach the other.
Move a real project recipe into sqlrs
Section titled “Move a real project recipe into sqlrs”Real recipes normally use one of these paths:
prepare:psqlfor SQL files, psql commands, and\ior\irinclude chains;prepare:lbfor a root Liquibase changelog and its included changelog files.
First make the raw form work:
sqlrs prepare:psql -- -f db/prepare.sql
Then store the command as a repository-tracked alias:
sqlrs alias create test-db prepare:psql -- -f db/prepare.sql
sqlrs prepare test-db
Commit test-db.prep.s9s.yaml; do not normally commit .sqlrs/. If you do not yet know where the
relevant SQL, changelog, or settings live, run sqlrs discover. Discovery reads the project and
suggests next steps; it does not create recipes, change configuration, or run migrations.
Choose an instance lifetime
Section titled “Choose an instance lifetime”For one SQL check, combine prepare and run. Local removes the temporary instance after psql exits:
sqlrs prepare test-db run:psql -- -f tests/db-smoke.sql
For a debugging session or several checks, keep the instance and address it explicitly:
sqlrs prepare test-db
sqlrs ls --instances
sqlrs run:psql --instance INSTANCE_ID -- -f tests/db-smoke.sql
For an application or ordinary test runner, pass the DSN from prepare through the environment. The existing-tests chapter provides PowerShell and POSIX examples.
Clean up safely
Section titled “Clean up safely”sqlrs rm INSTANCE_ID_PREFIX
sqlrs rm --dry-run --recurse STATE_ID_PREFIX
Use dry-run before recursive deletion. A state with instances or child states is protected without
--recurse; with the flag, Local evaluates the whole subtree before deleting anything. --force
may remove an instance with active connections, but it does not imply recursive deletion.