4 min read

Nobody Can Onboard Without a Working Local Database

New engineer, first morning. Laptop is set up. Repository cloned. They open the README and start working through setup.

Steps one to three are fine. Install the runtime, install dependencies, copy the environment file.

Step four says run the seed script. The seed script fails.

Now they are stuck, and they have been at the company for two hours, and they do not yet know who to ask or whether asking is normal. So they sit with it, which is the worst possible use of a new person's first day and also exactly what most of us did.

Why the script always rots

Seeding scripts break for a boring structural reason: nothing runs them.

CI does not run the seed script, because CI has its own fixtures. Production does not, obviously. Existing engineers do not, because their local database was seeded fourteen months ago and has been carried forward since.

So the only thing exercising that code path is onboarding, which happens a few times a year. The script is broken for months before anyone finds out, and the person who finds out is the one least equipped to fix it.

Meanwhile the schema moved. Columns were added with NOT NULL and no default. Tables were renamed. A new required foreign key appeared. Every one of those changes broke the script, and the migration that caused it passed all its tests, because the seed script is not in the test suite.

The workarounds are all bad

"Ask someone for their dump." This is the most common one and it is quietly the worst. It puts a copy of whatever that person had on a new laptop, and what that person had usually traces back to a production restore from a while ago. You have onboarded someone by handing them customer data, on day one, before their access review is done.

"Just point at shared dev." Now everybody develops against one database. Someone's migration breaks everyone. Someone's test data deletion breaks everyone. Nobody can experiment, because experiments are visible to the whole team.

"Here is a small fixture file." Better, and it is what many teams settle on. But small fixtures are usually too thin to work with. Twelve users and three orders will not let you see a pagination bug, a slow query, or anything that only appears at volume. You can run the app. You cannot really use it.

"Fix the script." The right answer, assigned to the newest person, who has the least context. It usually turns into a week of archaeology.

What a good local dataset needs

It needs to work today, against the schema as it exists right now, not as it existed when someone last touched the script.

It needs to be big enough to be usable. Not a million rows, but enough that lists paginate, search returns more than one result, and the UI looks like the product rather than a wireframe.

It needs to be safe. No real customer data on a new laptop. That should be non negotiable and it is routinely negotiated.

It needs to be repeatable. When the new engineer inevitably breaks their database in week two, getting back to a working state should take a minute, not a morning.

The generation approach

If the dataset is generated from the schema rather than maintained as a script, most of the rot problem disappears by construction.

Add a column next sprint, and the generator sees it the next time it reads the schema. There is no separate artefact holding a stale copy of the data model, because the schema is the model. Nothing to update, nothing to forget.

That is what SeedQL does. It introspects the database, works out the foreign key ordering, and fills it with data that satisfies the constraints. The new engineer runs it against their local Postgres and gets a working, populated database without touching a production backup or waiting on anyone.

Worth being clear about what this does not solve. It does not configure your application, install your dependencies, or set up your environment variables. It solves the specific step where a new person needs a database with plausible contents in it, which happens to be the step that fails most often and hurts most when it does.

And the free tier is deliberately enough for this. Local development is not a workload anyone should be paying for.

The measurement

Here is a cheap way to find out if you have this problem.

Next time someone joins, do not help them. Watch. Note the time they hit the first blocker and how long it takes to clear.

If the answer is "step four, most of a day", you do not have an onboarding documentation problem. You have a seed script that stopped working some time ago, and the only reason nobody noticed is that nobody else has needed it.

That is worth fixing before the next hire, not during.