Seeding

turbine seed runs a seed file to populate your database. The file can be TypeScript, JavaScript, or SQL; Turbine picks the right runner for each. TypeScript seeds run through tsx, so there is no separate build step.

npx turbine seed

defineSeed, TypeScript seeds#

defineSeed wraps a function that receives a connected client. It reads DATABASE_URL, runs your function, and disconnects when it's done. You don't manage the connection lifecycle.

// seed.ts
import { defineSeed } from 'turbine-orm';
 
export default defineSeed(async (db) => {
  await db.raw`
    INSERT INTO organizations (name, slug) VALUES (${'Acme'}, ${'acme'})
    ON CONFLICT (slug) DO NOTHING
  `;
  console.log('Seeded.');
});

The db handed to the callback is a base client: use db.raw or db.sql for inserts. For fully typed table accessors, import your generated client instead and manage its lifecycle yourself:

// seed.ts
import { turbine } from './generated/turbine/index.js';
 
const db = turbine({ connectionString: process.env.DATABASE_URL });
 
await db.organizations.createMany({
  data: [
    { name: 'Acme', slug: 'acme' },
    { name: 'Widgets', slug: 'widgets' },
  ],
});
 
await db.disconnect();

Either file runs the same way: npx turbine seed.

JavaScript and SQL seeds#

  • .js, imported dynamically. If the default export is a function, Turbine calls it.
  • .sql, executed as raw SQL against the database.
-- seed.sql
INSERT INTO organizations (name, slug) VALUES ('Acme', 'acme')
ON CONFLICT (slug) DO NOTHING;

Note: TypeScript seeds need tsx available (a dev dependency in most TypeScript projects). If it's missing, Turbine tells you to install tsx or use a .js / .sql seed instead.

File resolution#

Turbine resolves the seed file in this order:

  1. The seedFile field in turbine.config.ts. An explicit path always wins, even if the file doesn't exist yet.
  2. The first default candidate found: seed.ts, seed.js, seed.sql, turbine/seed.ts, turbine/seed.js, turbine/seed.sql.
// turbine.config.ts
import type { TurbineCliConfig } from 'turbine-orm/cli';
 
export default {
  url: process.env.DATABASE_URL,
  seedFile: './turbine/seed.ts',
} satisfies TurbineCliConfig;

seedFile is the canonical key and what turbine init writes. seed is a back-compat alias; when both are present, seedFile wins.

Seeding in CI/CD#

Pair migrate deploy with seed. migrate deploy applies pending migrations non-interactively, so it's safe in a pipeline; then seed on top:

# CI: bring a fresh database up to date, then seed it
npx turbine migrate deploy
npx turbine seed

migrate deploy refuses to run on a checksum mismatch or a missing migration file (exit 1), so a drifted migration history fails the build instead of silently diverging. See migrate deploy.

See also#

  • CLI, turbine seed, turbine migrate deploy, and every flag.
  • Schema & Migrations, the migration workflow seeds run on top of.
  • API Reference, createMany, raw, and sql for writing seed data.