Skip to main content
Episode 20 of 24Go live45 min

Create the online database and migrate it safely

Set up a free Neon Postgres database for production, run your migrations on it without risk, and rehearse a backup and restore.

You will have: An empty, migrated production database on Neon, two separate connection strings (pooled and direct), a tested backup and restore, and a guard that stops your local work from ever touching production data.

Before you start

  • Episodes 6 and 12 are done: your local database shop_local works and your migrations are committed in GitHub
  • A free Neon account (sign in with GitHub or email). The agent will ask you to create the project and paste only the connection strings into a file, never into chat
  • Postgres command line tools (pg_dump and psql) installed, or willingness to let the agent help install them
  • Your .env.local file open in an editor so you can paste two values into it

Make it yours

Change the example (a fashion store) to your own. Your answers are saved in this browser and used in every episode.

Other series keywords (5)

Your prompt

Paste into: Your AI agent (Claude Code or Codex) opened in your project folder (the same session style you used since Episode 4).
You are my careful database engineer. My store "Thread & Needle" is a fashion e-commerce store that sells women's and men's clothing, shoes and accessories, and I am working on macOS. It uses Postgres with Drizzle ORM and drizzle-kit migrations. Locally it uses a database called shop_local. Now I need the online production database on Neon (free plan) without risking any data.

Plan first: show me your plan and wait for my OK before changing anything.

Explain these in one sentence each as you go: pooled connection, direct connection, migration, backup, restore.

Tasks:
1. Guide me to create a Neon project in the region closest to my customers in United States. Tell me where to find two connection strings: the pooled one (the host name contains "-pooler") and the direct one. Do not ask me to paste them in chat.
2. Add two variable NAMES to .env.example with empty values: DATABASE_URL (pooled, used by the running website) and DATABASE_URL_DIRECT (direct, used only for migrations and backups). Tell me to paste the real values into .env.production.local, which must be git-ignored. Keep my existing local value in .env.local pointing to shop_local.
3. Check that the database code works with the pooled string (for example prepared statements may need to be switched off). Fix it if needed and explain the change.
4. Add a safety guard: a small shared function that every script (migrate, seed, backup) calls first. It must refuse to run against a host containing "neon.tech" unless I pass an explicit flag such as --production. Local development and tests must always use shop_local. Show me the guard working by trying to run a script against production without the flag.
5. Run the migrations on Neon using the direct connection. First list the pending migrations and read me any that drop or rename anything. Run only after I say yes. Do not seed fake products into production.
6. Create the first admin user in production in the safest way (a one-time script that reads email and password from the terminal prompt, never from a file or chat). Hash the password.
7. Backup and restore rehearsal: make a backup with pg_dump through the direct connection into a folder named backups/ (add it to .gitignore, as dumps contain customer data). Create a scratch Neon branch or a scratch local database named shop_restore_test, restore the backup into it, and compare row counts of the main tables. Then delete the scratch database.
8. Write DATABASE.md in plain language: which URL is used where, how to run a production migration, how to back up, how to restore, and a warning never to copy production data to a laptop without a reason.

Security rules: never print, log or commit a connection string or password. Never run any destructive SQL (drop, truncate, delete) on production. If something looks wrong, stop and ask me.

Verify yourself: show the list of tables on Neon, the migration status on Neon and on shop_local, the row counts after the restore rehearsal, and the output of the guard blocking an unsafe run. Mask any secrets in the output.

Commit to git with a clear message such as "Add production database setup, guard and backup scripts".

Report back in this format:
- What was done
- What I should check (including what to look at in the Neon dashboard)
- Anything that needs my decision

Review the prompt, then copy it. Never paste real passwords or API keys into a chat.

How to check it worked

  • In the Neon dashboard you can see your project and the tables created by your migrations
  • Running a script against the online database without the --production flag is refused with a clear message
  • .env.example lists DATABASE_URL and DATABASE_URL_DIRECT with no values, and git status shows no .env file as changed
  • A backup file exists in backups/ and git does not list it
  • The restore rehearsal shows the same row counts in the scratch copy as in the original
  • Your local site still opens and shows your test products from shop_local

Sample result

Fashion store example

Example report for the fashion store. Your table names and counts will differ, and hosts are masked.

If something goes wrong

The migration fails with a message about prepared statements or a connection that is closed.
You probably ran the migration on the pooled string. Run it with DATABASE_URL_DIRECT. If the running website shows the error, tell the agent: "Make the app database client compatible with the pooled connection."
The first request after a quiet period is slow or times out.
Free databases may pause when idle and wake on the next request. Retry once. If it keeps failing, ask the agent to add a short connection timeout and a friendly error page, and check the plan limits on Neon's pricing page.
pg_dump says the version is older than the server.
Install a Postgres client with the same major version as your Neon project (shown in the Neon dashboard) and ask the agent to use it for backups.
The guard blocks a script you really need to run on production.
That is the guard working. Read what the script will do, then ask the agent to run it again with the --production flag and show you the result.

Neon has a free plan, but storage, compute hours and backup history limits change. Verify them on Neon's pricing page before launch, and check how far back its point-in-time restore goes on the free plan, because your own pg_dump backup is the one you control.

More in Go live

This is part of the series Build a secure, no-cost e-commerce website with AI agents. See all 24 episodes, the tools used and answers to common questions on the series page.

We use optional cookies for analytics and referral tracking. Learn more about our privacy policy