Production and deployment
Add observability
Use structured logs, traces, request IDs, and platform metrics without leaking secrets, authorization values, or personal link data.
When a user says “my export failed”, you need to find that one invocation among thousands, see what it did, and see which binding call went wrong. That’s observability. Without it you’re guessing.
Turn on Workers Logs
Cloudflare stores your Worker’s logs only if you ask. One line in wrangler.jsonc:
{
"observability": { "enabled": true }
}
Deploy, and every console.log from production is retained and searchable in the dashboard, with the invocation’s status, duration, and version attached.
Log JSON, not sentences
A structured line is filterable. A sentence is not. Log one object per event:
console.log(JSON.stringify({
requestId,
route: '/api/links/:id',
status: 404,
durationMs: 12,
binding: 'd1.first'
}))
Notice the route is the template, /api/links/:id, not the real path. The real path carries a user’s link ID. The template groups a thousand requests into one line you can count.
Propagate one ID
Generate a request ID at the edge of every request, put it in the response header, and include it in every log line for that request. When the export job goes to the queue, carry the job ID along and log it in the consumer too. Now one ID connects the HTTP request that started the export, the queue message, and the R2 write.
Add the Worker version ID as well. When errors spike, the first question is “did we just deploy?”, and this answers it in one query.
Logs, metrics, traces
They answer different questions. Logs say what happened in one execution. Metrics say how often, and which way the trend is moving. Traces show where time went. Use logs to debug a report, metrics to notice a problem, traces to find the slow part.
What never goes in a log
Tokens, secrets, cookies, Authorization headers, full private URLs, export contents. If a field could hurt someone in a public paste, it doesn’t belong there. Log the error class and message, not the whole request.
Tail is for now, not for later
wrangler tail streams live logs to your terminal. Use it while reproducing a bug. Don’t rely on it for history: it can sample under load, and it stores nothing. Production needs retained Workers Logs plus an alert on the 5xx rate.
Prove an operator can find it
Deploy, then break things on purpose in a safe way. Request /api/links/does-not-exist for a 404, and point a staging binding at an empty database for one controlled dependency error. Then find both events in the dashboard by request ID, without searching for any private content.
Now add two log lines to Link Vault: one per HTTP request, with the fields above, and one per queue job, with the job ID and final state. Check them in npm run dev output first, then deploy and watch them arrive in wrangler tail.
Lesson completed