{"slug": "testing-cloudflare-cron-triggers-locally-for-push-notification-workflows", "title": "Testing Cloudflare Cron Triggers Locally for Push Notification Workflows", "summary": "A developer detailed a method for locally testing Cloudflare Workers Cron Triggers used for push notification workflows. By separating the scheduled event from an internal HTTP route, the same logic can be triggered via HTTP, simplifying verification. The approach uses Wrangler's --test-scheduled flag and direct route calls to validate cron wiring and notification logic independently.", "body_md": "*This article is an English translation of the original Japanese article.*\n\nI use Cloudflare Workers Cron Triggers to send push notifications on the morning of practice days. The challenge was figuring out how to verify the entire workflow locally without waiting for the scheduled cron time.\n\nIn my implementation, I separate the Worker's `scheduled`\n\nevent from the HTTP route that handles the notification logic.\n\nThe Worker receives the cron event and calls an internal route handler.\n\n```\nexport default {\n  async fetch(request: Request, env: Env, ctx: ExecutionContext) {\n    return handler.fetch(request, env, ctx);\n  },\n\n  async scheduled(_controller: ScheduledController, env: Env) {\n    const request = new Request(\n      \"https://internal/api/cron/morning-reminder\",\n      {\n        method: \"POST\",\n        headers: { authorization: `Bearer ${env.CRON_SECRET}` },\n      },\n    );\n\n    await handler.fetch(request, env);\n  },\n};\n```\n\nThe key is not embedding date logic, user retrieval, and Expo Push API calls directly inside `scheduled`\n\n. Delegating to an HTTP route means the same logic can be triggered over HTTP, making local verification much easier.\n\nLocally, start Wrangler with the following option:\n\n```\nnpx wrangler dev --test-scheduled\n```\n\nAppend `/__scheduled`\n\nto the URL Wrangler displays.\n\n```\ncurl \"http://localhost:8787/__scheduled?cron=0+22+*+*+*\"\n```\n\nUse the same cron expression in the `cron`\n\nquery parameter. Cloudflare interprets cron in UTC, so don't write expressions based solely on JST.\n\nWhen you only want to verify recipient filtering, you can call the internal route directly.\n\n```\ncurl -X POST http://localhost:8787/api/cron/morning-reminder \\\n  -H \"Authorization: Bearer $CRON_SECRET\"\n```\n\nThis route validates `CRON_SECRET`\n\n. Rather than removing authentication for local development, I store a development value in `.dev.vars`\n\n. Production secrets never go into source control.\n\nIf your local database has no schedules, participants, or push tokens for today, the cron will run but send zero notifications. When testing, verify in order:\n\n`scheduled`\n\nreach the route?The hard part of cron testing is not how to trigger it, but coordinating test data with the current time. Splitting the core logic into an HTTP route lets you verify event wiring and notification logic separately.", "url": "https://wpnews.pro/news/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows", "canonical_source": "https://dev.to/hirodeath/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows-161b", "published_at": "2026-08-10 00:44:05+00:00", "updated_at": "2026-08-10 01:16:31.387675+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Cloudflare Workers", "Wrangler", "Expo Push API"], "alternates": {"html": "https://wpnews.pro/news/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows", "markdown": "https://wpnews.pro/news/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows.md", "text": "https://wpnews.pro/news/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows.txt", "jsonld": "https://wpnews.pro/news/testing-cloudflare-cron-triggers-locally-for-push-notification-workflows.jsonld"}}