The first plugin in the list, and the only one that opens a resource in
onPluginInit. It contributes no routes and no UI. What it gives the rest of
the system is three things: a connection pool, a transaction boundary, and a
transactional outbox.
Install
npm install @apograph/databaseRegister
import { DatabasePlugin } from '@apograph/database';
DatabasePlugin({ connectionString: config.database.url });It goes first. Every other plugin’s migrations and repositories resolve against the connection it opens.
Environment
| Variable | Default | What it does |
|---|---|---|
DATABASE_URL | none — required | Postgres connection string. The app refuses to load without it |
There is no usable default. Left unset, the value reaches pg as “use the
libpq defaults” and the first query fails with whatever the local environment
happens to produce — a message that names everything except the variable nobody
set. apograph.config.ts fails at load instead.
What it gives other plugins
The pool. InjectDatabase hands a plugin the Drizzle instance. Nothing
else opens a connection.
import { InjectDatabase, type Database } from '@apograph/database';
class EntryRepository {
constructor(@InjectDatabase() private readonly db: Database) {}
}The unit of work. UnitOfWork.run is the transaction boundary a state
change happens inside. Every write in a use case — the row, its revision, and
its domain event — commits together or not at all.
The outbox. Domain events are written to outbox_events in the same
transaction as the row that caused them, then dispatched after the commit. That
is what makes the activity log a subscriber rather
than a second write nobody can roll back.
The pool drains on shutdown
Shutdown waits for the in-flight outbox batch and then closes the pool, so a deploy does not sever a dispatch mid-flight.
Migrations
Every plugin ships its own migrations and owns its own __drizzle_migrations_*
table. apograph migrate walks the plugin list in order and applies each one —
see the database and migrations for the deployment
sequence, and the CLI for the commands.