Fixing Prisma Shadow Database Failures

You ran prisma migrate dev against a managed Postgres instance and it stopped on P3014Prisma Migrate could not create the shadow database — or it created one but then died on P3006 while migrating it. The command worked on your laptop’s local Postgres and breaks the instant it points at a provider like Supabase, Neon, RDS, or Cloud SQL. The cause is almost never your schema; it is that the database role Prisma is connecting as does not have permission to CREATE DATABASE, which is exactly what the shadow database mechanism requires. This page is the fix: provision a dedicated shadow database, wire it through shadowDatabaseUrl, and grant the right permissions, all of which is detailed at the level of the parent Prisma Migration Strategies guide.

These errors only ever come from development-time commands. prisma migrate deploy — the command you run in production — never touches a shadow database, so a P3014 in CI on a deploy step means your pipeline is wrongly invoking migrate dev somewhere, which is its own bug to fix as part of the broader ORM & Framework Migration Workflows discipline.

Why the shadow database fails and how shadowDatabaseUrl fixes it Top path: migrate dev asks the managed database to CREATE DATABASE and is denied because the role lacks the privilege, producing P3014. Bottom path: shadowDatabaseUrl points at a pre-provisioned dedicated shadow database, so no CREATE DATABASE is needed. Auto-Create (fails) vs Dedicated Shadow DB (works) migrate dev CREATE DATABASE (needs privilege) DENIED P3014 migrate dev shadowDatabaseUrl dedicated empty shadow database works No CREATE DATABASE call is made when shadowDatabaseUrl points at an existing database.
The default path asks the provider to create a database and is denied; pointing shadowDatabaseUrl at a pre-made empty database removes the privileged call entirely.

Symptom / Error Signatures

The two error codes look different but share one root. The first is the auto-create denial:

Error: P3014
Prisma Migrate could not create the shadow database. Please make sure the database
user has permission to create databases. Read more about the shadow database (and
its requirements) here: https://pris.ly/d/migrate-shadow

Original error: ERROR: permission denied to create database

The second appears after the shadow database exists but Prisma fails while migrating it — replaying your history onto the shadow copy errors out:

Error: P3006
Migration `20260614_add_orders` failed to apply cleanly to the shadow database.
Error: ERROR: type "vector" does not exist
   0: schema_core::commands::...

A P3006 typically means the shadow database is missing an extension, role, or pre-existing object that your real database has but a freshly created empty database does not. Both P3014 and P3006 are raised only by prisma migrate dev, prisma migrate reset, and prisma db push --force-reset; if you see either from a step that was supposed to be prisma migrate deploy, the wrong command is wired in.

Root Cause Analysis

Prisma’s migrate dev cannot trust your development database to tell it what the next migration should be, because that database might already contain hand-applied changes. So it builds a clean reference: it creates a brand-new database, replays every committed migration onto it, and diffs the result against schema.prisma. That brand-new database is the shadow database, and creating it is a privileged operation. On a local Postgres where your superuser owns everything, Prisma silently issues CREATE DATABASE, uses it, and drops it. On managed Postgres the application role you connect as is deliberately stripped of CREATEDB, so the very first step fails with P3014.

P3006 is the second-order version: you gave Prisma a shadow database, but replaying the history onto it fails because the empty shadow is not a faithful copy of production. The usual culprits are extensions your migrations assume already exist (CREATE EXTENSION "uuid-ossp", vector, postgis), roles referenced by GRANT statements, or objects created outside the migration history. The two errors trade off along the privilege axis: the more locked-down the provider, the more likely you hit P3014 first; once you supply a shadow URL, any non-self-contained migration surfaces as P3006.

Situation Error Underlying cause Direction of fix
Local Postgres, superuser role none role has CREATEDB; shadow auto-created and dropped nothing to do
Managed Postgres, app role P3014 role lacks CREATEDB; auto-create denied provision a dedicated shadow DB + shadowDatabaseUrl
Shadow DB supplied but history assumes an extension P3006 empty shadow lacks CREATE EXTENSION, roles, or seed objects make migrations self-contained (CREATE EXTENSION IF NOT EXISTS) or pre-provision the shadow
Provider blocks DROP/CREATE even with a shadow URL P3014 persists role cannot reset the supplied shadow between runs grant the role ownership of the shadow database

Immediate Mitigation

The fastest path back to a working migrate dev is to stop asking the provider to create anything.

1. Create a dedicated, empty shadow database once, by hand, using an admin connection (the provider console, or a role that does have CREATEDB).

-- PostgreSQL · run as an admin/superuser role · one-time setup, NOT part of any migration.
CREATE DATABASE myapp_shadow;

2. Grant your migration role full ownership of it so Prisma can drop and recreate its contents on every migrate dev run.

-- PostgreSQL · run as admin · the migration role must own the shadow DB to reset it between runs.
ALTER DATABASE myapp_shadow OWNER TO myapp_migrator;
GRANT ALL PRIVILEGES ON DATABASE myapp_shadow TO myapp_migrator;

3. Point Prisma at it with shadowDatabaseUrl in your datasource block, sourced from an environment variable so the credentials never land in version control.

// prisma/schema.prisma · local/CI authoring only · shadowDatabaseUrl is ignored by migrate deploy.
datasource db {
  provider          = "postgresql"
  url               = env("DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
# .env (local) — never commit · SHADOW_DATABASE_URL must point at the dedicated empty database above.
SHADOW_DATABASE_URL="postgresql://myapp_migrator:***@db.example.com:5432/myapp_shadow"

4. If you then hit P3006, make the failing migration self-contained so it succeeds on an empty shadow — guard every extension and seed object:

-- PostgreSQL · inside the migration · IF NOT EXISTS makes it replay cleanly on the empty shadow DB.
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "vector";

Permanent Fix / Long-Term Pattern

The durable arrangement separates the two database roles by intent. Production uses a least-privilege role with no CREATEDB and runs only prisma migrate deploy, which never needs a shadow database at all — so production never trips P3014. Local and CI authoring use a role that owns a dedicated, persistent shadow database supplied through shadowDatabaseUrl. Keeping a single long-lived shadow database, rather than letting each developer’s tooling try to create one, also makes P3006 reproducible: if a migration fails on the shared shadow it fails for everyone, and you catch the missing-extension class of bug before it reaches a teammate.

Make your migrations self-contained as a rule, not a patch. Every CREATE EXTENSION uses IF NOT EXISTS, every dependency on a role or object is created within the migration history rather than assumed, and the empty-database replay that the shadow database performs becomes a free correctness check on every migrate dev. This is the same drift- and parity-discipline the parent Prisma Migration Strategies guide applies to the whole history, and it dovetails with the environment parity strategies that keep development and production schemas reproducible from the same artifacts. Once authoring is solid, the next operational hurdle in the same toolchain is usually pool contention during the deploy itself, covered in resolving Prisma connection pool timeouts.

Verification Checklist

  • prisma migrate dev completes against the managed database without P3014 or P3006.
  • shadowDatabaseUrl is set from an environment variable and the value is absent from version control.
  • IF NOT EXISTS so it replays on an empty shadow.
  • prisma migrate deploy only — no shadowDatabaseUrl dependency on the production path.
  • CREATEDB, confirming the shadow mechanism is never invoked there.

Frequently Asked Questions

Why does migrate dev work locally but fail with P3014 on my hosted database? Local Postgres usually runs as a superuser role that has CREATEDB, so Prisma silently creates and drops the shadow database. Managed providers strip CREATEDB from application roles for safety, so the auto-create step is denied. Provision a dedicated shadow database yourself and point shadowDatabaseUrl at it so Prisma never has to create one.

Does production need a shadow database? No. The shadow database is only used by development-time commands like prisma migrate dev and prisma migrate reset. Production runs prisma migrate deploy, which applies committed migrations directly and never creates or migrates a shadow database. A P3014 in production means a non-deploy command is wrongly wired into the pipeline.

I set shadowDatabaseUrl but now I get P3006 instead — what changed? P3014 was the database refusing to be created; P3006 is your migration history failing to replay onto the now-available empty shadow. The shadow starts blank, so any migration that assumes an extension, role, or object already exists will fail. Make those migrations self-contained with CREATE EXTENSION IF NOT EXISTS and explicit object creation.

Can two developers share one shadow database? They can share one shadow server, but each authoring context should target a database the migration role owns so Prisma can reset it cleanly between runs. A single shared shadow database is fine for CI; for parallel local development, give each developer their own shadow database to avoid one migrate dev resetting another’s in-progress state.