Chapter 04 · Cloudflare Deploy
Subchapter 4.120
references/miniflare/gotchas.mdMarkdown4 KBView on GitHub
Not supported:
Behavior differences from production:
Request.cf is cached/mocked, not real edge dataCause: Module path wrong or modulesRules not configured
Solution:
new Miniflare({
modules: true,
modulesRules: [{ type: "ESModule", include: ["**/*.js"] }],
});Cause: Persist paths are files, not directories
Solution:
kvPersist: "./data/kv", // Directory, not fileCause: Miniflare doesn’t transpile TypeScript
Solution: Build first with esbuild/tsc, then run compiled JS
Cause: CF data not configured
Solution:
new Miniflare({ cf: true }); // Or cf: "./cf.json"Cause: Multiple instances using same port
Solution: Use dispatchFetch() (no HTTP server) or port: 0 for auto-assign
Cause: Class export doesn’t match config name
Solution:
export class Counter {} // Must match
new Miniflare({ durableObjects: { COUNTER: "Counter" } });Enable verbose logging:
import { Log, LogLevel } from "miniflare";
new Miniflare({ log: new Log(LogLevel.DEBUG) });Chrome DevTools:
const url = await mf.getInspectorURL();
console.log(`DevTools: ${url}`); // Open in ChromeInspect bindings:
const env = await mf.getBindings();
console.log(Object.keys(env));Verify storage:
const ns = await mf.getKVNamespace("TEST");
const { keys } = await ns.list();✓ Do:
dispatchFetch() for tests (no HTTP server)await mf.dispose() in cleanup✗ Avoid:
Breaking changes in v3+:
| v2 | v3+ |
|---|---|
getBindings() sync | getBindings() returns Promise |
ready is void | ready returns Promise<URL> |
| service-worker-mock | Built on workerd |
| Different options | Restructured constructor |
Example migration:
// v2
const bindings = mf.getBindings();
mf.ready; // void
// v3+
const bindings = await mf.getBindings();
const url = await mf.ready; // Promise<URL>// Old (deprecated)
import { unstable_dev } from "wrangler";
const worker = await unstable_dev("src/index.ts");
// New
import { Miniflare } from "miniflare";
const mf = new Miniflare({ scriptPath: "src/index.ts" });Miniflare doesn’t auto-read wrangler.toml:
// Translate manually:
new Miniflare({
scriptPath: "dist/worker.js",
compatibilityDate: "2026-01-01",
kvNamespaces: ["KV"],
bindings: { API_KEY: process.env.API_KEY },
});| Limit | Value | Notes |
|---|---|---|
| CPU time | 30s default | Configurable via scriptTimeout |
| Storage | Filesystem | Performance varies by disk |
| Memory | System dependent | No artificial limits |
| Request.cf | Cached/mocked | Not live edge data |
See patterns.md for testing examples.