Download production D1 data to local
When your app is live on Cloudflare, your D1 database lives at the edge. Here’s how to pull that data down to your local machine for debugging, backups, or offline development.
The one-command export
Section titled “The one-command export”wrangler d1 execute <database-name> --remote --command "SELECT * FROM users" --output users.jsonThis runs a SQL query against your remote D1 database and writes the
results to a JSON file. Replace <database-name> with your D1 database name
from wrangler.toml.
Export all tables
Section titled “Export all tables”The starter includes four tables: users, sessions, password_resets,
and uploads. To export everything:
# Export each table to JSONwrangler d1 execute <database-name> --remote --command "SELECT * FROM users" --output export/users.jsonwrangler d1 execute <database-name> --remote --command "SELECT * FROM sessions" --output export/sessions.jsonwrangler d1 execute <database-name> --remote --command "SELECT * FROM password_resets" --output export/password_resets.jsonwrangler d1 execute <database-name> --remote --command "SELECT * FROM uploads" --output export/uploads.jsonImport into local D1
Section titled “Import into local D1”After exporting, push the data into your local D1 database:
# Apply migrations first (if local DB is empty)wrangler d1 migrations apply <database-name> --local
# Import each tablewrangler d1 execute <database-name> --local --file export/users.jsonwrangler d1 execute <database-name> --local --file export/sessions.jsonwrangler d1 execute <database-name> --local --file export/password_resets.jsonwrangler d1 execute <database-name> --local --file export/uploads.jsonExport as raw SQL
Section titled “Export as raw SQL”If you prefer a SQL dump (like pg_dump), use the --export flag:
wrangler d1 execute <database-name> --remote --export ./backup.sqlThis produces a .sql file with INSERT statements for all tables. To
restore locally:
wrangler d1 execute <database-name> --local --file ./backup.sqlAutomate it
Section titled “Automate it”Add a script to your package.json:
{ "scripts": { "db:pull": "wrangler d1 execute <database-name> --remote --export ./backup.sql && wrangler d1 execute <database-name> --local --file ./backup.sql" }}Then bun run db:pull syncs remote to local in one step.
What about uploaded files?
Section titled “What about uploaded files?”D1 only stores database rows. If your app has file uploads (avatars, etc.), those live on disk or in R2 — not in D1. To download uploaded files from production, you’ll need to fetch them via HTTP or sync from your R2 bucket:
# If using R2 for uploadswrangler r2 object get <bucket-name>/avatar-123.png ./local-uploads/avatar-123.pngCaveats
Section titled “Caveats”--remotehits your production database — read queries are safe, but never runDELETEorUPDATEwith--remoteunless you mean it.- D1 export is not a full backup — it exports data, not schema. Schema
lives in your
migrations/folder, which is version-controlled. - Large exports may time out — D1 has a 30-second query duration limit.
For very large tables, export in chunks with
LIMITandOFFSET.