Cloudflare Workers gives you a powerful serverless runtime at the edge, but
console.log output disappears after the request ends. Here’s how to build a
real log monitoring system that persists, queries, and alerts on your logs.
Why console.log isn’t enough
When debugging locally, wrangler dev shows console output inline. In production,
Workers logs are available in the Cloudflare dashboard for a limited window —
but you can’t search them, set up alerts, or correlate them across requests.
For any app beyond a prototype, you need:
- Persistent storage — logs available hours or days later
- Structured data — JSON fields you can filter and query
- Alerting — notifications when error rates spike
- Session correlation — trace a user’s journey across multiple requests
Option 1: Use ScryWatch (5 minutes)
ScryWatch runs on the same Cloudflare infrastructure as your Workers. Send logs
with a single fetch:
async function log(env, level, message, fields = {}) {
await fetch('https://ingest.scrywatch.com/v1/logs', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.SCRYWATCH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
level,
message,
service: 'my-worker',
...fields,
}),
});
}
Then in your Worker handler:
export default {
async fetch(request, env, ctx) {
ctx.waitUntil(log(env, 'info', 'Request received', {
path: new URL(request.url).pathname,
method: request.method,
}));
// your handler logic...
}
};
ctx.waitUntil ensures the log is sent without blocking the response.
Option 2: Use Cloudflare Logpush (complex)
Cloudflare Logpush can forward Worker logs to S3, R2, or a SIEM. It requires:
- Configuring a Logpush job via the API
- Standing up a log aggregation pipeline
- Building your own query interface
This works well at scale but takes days to set up correctly.
Structured logging best practices
Regardless of which approach you use:
- Always use JSON —
{ level: 'error', message: '...', userId: '...' }not plain strings - Add a service field — makes it easy to filter by microservice
- Log at request boundaries — start, end, and any errors
- Use
ctx.waitUntil— neverawaitlog calls in the critical path
Summary
console.logworks for local dev only- ScryWatch gives you production log monitoring in 5 minutes with no infrastructure
- Always send structured JSON logs with a service identifier