Ask
29

I keep losing track of which database I just changed, how do people keep local and production straight?

Working on a Workers app with D1. I have run migrations locally, run them against production, seeded test data, and at this point I genuinely do not know which database has what.

Twice now I have queried something, seen unexpected data, and spent twenty minutes debugging before realising I was looking at the wrong one. Once I ran a delete that I am fairly sure went where I intended, and I am only fairly sure.

The commands look almost identical, the output looks identical, and the only difference is a flag I sometimes forget.

How do people actually structure this so it is not a constant hazard? I would like a setup where getting it wrong is hard rather than one where I have to be careful.

3 answers Share
Report

Answering anonymously, a moderator will review it first.

  • @flag_discipline · 3w ago

    On making the mistake hard rather than relying on care, a few things that actually work:

    Never alias or script the remote flag away. The typing is the safety mechanism. Anything that makes hitting production as convenient as hitting local removes the only friction you have.

    Put the destructive commands in named scripts that state their target in the name. Something you invoke by a name containing the word production is a different act from adding a flag to a command you run all day.

    Make the prompt tell you. If you spend a lot of time in these commands, having the environment visible in your shell prompt or terminal title is worth the setup.

    Read the output. Wrangler prints which database and which environment it acted on. It is easy to skim past and it is the confirmation you already have.

    Query something identifying before you write. A single select of a row count, or of a known test row, takes two seconds and tells you where you are. I do this before anything destructive and it has caught me twice.

    And for genuinely destructive operations on production, the honest answer is to not run them ad hoc at all. Put them in a migration or a reviewed script, so there is a record and a moment of deliberation.

    26
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @two_databases_two · 3w ago

    The mental model that fixes most of this: local and remote are two unrelated databases that happen to share a schema. Not two copies, not two environments of one thing. Two databases.

    Once you hold that, the confusion largely stops, because you stop expecting them to resemble each other and you start asking which one you mean before every command.

    What follows from it:

    Local is disposable. It lives in a directory under your project and you should be willing to delete it at any moment. If deleting your local database is scary, you have put something in it that only exists there, and that is the actual problem.

    Remote is the only thing that matters. Everything in it is real. Nothing about it should ever depend on something you did by hand.

    They will diverge and that is fine. Local has test junk; production has real rows. Trying to keep them in sync is a losing game and not a goal.

    The practical consequence for your delete incident: make local reproducible so you never have to protect it. A schema plus a seed script that runs in one command. Then wiping local is a thirty second inconvenience rather than a loss, and the only database you have to be careful with is the one you should be careful with anyway.

    30
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report
  • @seed_local_only · 3w ago

    The migration question underneath this is worth separating, because it is where the divergence starts.

    Migrations are the only thing that should ever change schema, in either database. If you have ever run an ad hoc alter statement against one of them, they are now different in a way no tool will tell you about, and that is usually the origin of the wrong-database confusion - you are seeing a difference and assuming it is data when it is schema.

    So:

    Apply migrations to local first, always. That is what local is for. If it fails there, it would have failed in production.

    Apply to remote as a deliberate step, ideally from your deploy process rather than from your terminal, so it is recorded and repeatable.

    Never edit an applied migration. Add a new one. This is true everywhere and it is especially true when two databases are at different points in the sequence.

    Keep seed data out of the migrations directory. This one has bitten people badly: a seed file that lives among migrations gets applied to production the next time migrations run, and if it contains a delete to make it re-runnable, it deletes real rows. Seeds are a separate command, applied only to local, by hand.

    1
    Share
    Reply

    Answering anonymously, a moderator will review it first.

    Report