DEV Community

wrangler dev --remote silently writes to your production KV namespace - here's the fix

I lost production data on a Tuesday afternoon because wrangler.toml had one missing field. Not a code bug. Not a logic error. A missing preview_id.

By default, wrangler dev uses a local SQLite simulation - safe, isolated, zero real traffic. The moment you add --remote, every KV read and write goes to the actual Cloudflare namespace over the API. If your wrangler.toml only has the id field pointing at your production namespace, those writes land in prod. No warning. No confirmation prompt. Just silent data mutation on the namespace your live users depend on.

The fix

The fix is a single extra field:

[[kv_namespaces]]
binding = "MY_STORE"
id = "PROD_NAMESPACE_ID_HERE"
preview_id = "DEV_NAMESPACE_ID_HERE"

Wrangler automatically routes --remote traffic through preview_id instead of id. Create a separate dev namespace with wrangler kv namespace create "MY_STORE_dev", drop its ID into preview_id, and your production namespace is untouched.

This should probably be in the quickstart docs. It isn't, at least not prominently.

Behavioral gap exposed by --remote

The second thing worth knowing: --remote exposes a behavioral gap that local simulation hides entirely. Local KV is synchronous and in-process - a put() followed by a get() on the same key always returns the fresh value. Remote KV is eventually consistent.

I had a rate-limiting worker that looked completely broken under --remote: I'd write a counter, immediately read it back, and get the old value. The worker was correct. The local simulation had been lying to me about how production actually behaves. Switching to --remote (against a dev namespace, not prod) surfaced the real race condition. That's uncomfortable, but it's accurate.

Write-rate ceiling

There's also a write-rate ceiling worth knowing before you run any kind of seed script: hit roughly 1,000 writes/minute and you'll start seeing 429 Too Many Requests with error code 10013. A 70ms sleep between writes keeps you under the limit without dramatically slowing a seed operation down.

I wrote up the full breakdown - including the wrangler tail JSON truncation trap that cost me two hours, a shell script for seeding a dev namespace with representative data, and the exact cacheTtl: 0 pattern for honest read behavior - over on dailymanuallab.com.

Comments

No comments yet. Start the discussion.