Seed Data
elements man database/seeds Read as markdownDemo rows for development, reference rows for every environment, and the
@migration env= option that scopes a migration to the environments it names.
Seed data is a migration. There is no separate seed command and no seeds
directory. A migration file tagged @migration env=development applies to your local
database and never reaches production. An untagged migration applies
everywhere, so rows every environment needs go in an ordinary migration.
Development Seed Rows
Create a migration and tag it in a /** */ comment before the first statement:
Terminalelements create migration "demo rows"
app/migrations/20260509120000-demo-rows.migration.sql/** @migration env=development */ insert into users ( email, name ) values ( 'ada@example.com', 'Ada' ), ( 'grace@example.com', 'Grace' ); insert into projects (name, ownerId) select 'Demo project', id from users where email = 'ada@example.com';
Save it and the build applies it to the development database, in filename order with every other migration, so it can insert into any table an earlier migration created. On a deploy machine the file is skipped: it is never applied, never pending, and leaves no record in the database.
Write the whole file, then save it once. Saving a migration that has already
applied is an edit, and in development an edit restores the database from the
backup taken before that migration first applied, or rebuilds it from every
migration when no backup is left (see elements man migrations). Every save of
a seed file resets the rows added since, and signs out anyone who signed in
since. Editing a seed file five times resets the database five times.
The Tag
Build tags are JSDoc comments, and @migration is no exception. It goes in a
/** */ comment among the file's leading comments, before the first SQL
statement. A description comment can come first:
app/migrations/20260509120000-demo-rows.migration.sql-- demo rows for local work /** * @migration env=development */ insert into users ( email, name ) values ( 'ada@example.com', 'Ada' );
List more than one environment with commas and no spaces:
Example/** @migration env=development,staging */
Names are environments of this project: development, production, and any
environment with its own config/env/<name>.env file or deploy.env.<name>
block (see elements man config). A name that is none of these is a build
error naming the environments that exist, and no migration runs until it is
fixed. A @migration in a /* */ or -- comment, an env= with no names, or
an unknown option is also an error rather than a tag that silently does
nothing. env combines with the other options of the tag, such as tx=false
(see elements man migrations).
Which Database Gets What
| File | Development | Production | Staging |
|---|---|---|---|
| untagged | applied | applied | applied |
env=development |
applied | skipped | skipped |
env=production |
skipped | applied | skipped |
env=development,production |
applied | applied | skipped |
The test database is not an environment. Every environment has an app
database and a test database, and both get the same migrations, so in
development the test database carries the seed rows too. Tests assert on the
rows they create, not on whole tables (see elements man tests).
Reference Rows
Rows the app cannot run without, such as a lookup table's values or the single
row a cache table starts with, go in an untagged migration. They apply in every
environment and on the test database. elements man recipes/cron-cache inserts
its starting row this way.
Changing a Migration's Environments
Do not add env= to a migration that has already applied. The tag is part of
the file, so adding it changes the file's content, which is an edit. Development
resets. A deploy machine rejects the changed migration as stale, or, when the
tag leaves its environment out, skips the file from then on without undoing the
rows it already inserted. Put the rows in a new tagged migration instead.
Removing the tag from a development seed later is allowed. Development treats it as an edit and resets. Production has no record of the file, so the next deploy applies it there for the first time.
Running the server locally with ENV=production uses the same local database
as development. A development seed that already applied stays in it; the file
is only skipped, never undone.
Related
elements man migrations: how migrations apply, edit, and revert.elements man config: environments and env files.elements man database/cli: piping a one-off SQL file intoelements db.