The best cron job services for 2026: an honest comparison
You want to run an HTTP request on a schedule. Hit an endpoint every night, poll an API, fire a webhook. Go shopping for that and you’ll find two very different kinds of product answering to the name “job scheduler,” and most comparison lists won’t tell you which is which. It’s easy to pick the wrong kind before you’ve finished the pricing page.
Disclosure up front: I build one of the tools on this list, Smpl Jobs. I’ve put it where I think it belongs and said where the others are stronger.
The two kinds of “job scheduler”
Cloud-platform schedulers trigger your code. AWS EventBridge Scheduler, Cloudflare Workers Cron Triggers, GitHub Actions, Google Cloud Scheduler, and Vercel Cron Jobs all live here. They fire on a schedule and hand your code a trigger. Capturing the response, keeping a history of runs, and querying that history later are yours to build, out of compute, storage, and an endpoint. Some of them only speak UTC.
Managed cron-as-a-service calls your URL and saves what came back. cron-job.org, EasyCron, Posthook, Runhooks, Smpl Jobs, and Upstash QStash live here — though as you’ll see, a couple of them are in this camp on a technicality. You give them a URL and a schedule. They make the call, and most of them record the response and keep the history. Nothing to deploy, no database to wire up.
Trigger your code
Fires on a schedule and hands you a trigger. Response capture and run history are yours to build.
- AWS EventBridge Scheduler
- Cloudflare Workers Cron
- GitHub Actions
- Google Cloud Scheduler
- Vercel Cron
Call your URL & capture the response
Takes a URL and a schedule; makes the call, records what came back, and keeps the history.
- cron-job.org
- EasyCron
- Posthook
- Runhooks
- Smpl Jobs
- Upstash QStash
Most “hit an API on a schedule and keep the result” tasks are the second kind. But the first camp has the name recognition, so that’s where people start. A few days later they’re maintaining a small internal service whose only feature is remembering whether last night’s job ran.
The field at a glance
| Service | Type | Timezone | Captures response | History API | Retries | Free tier |
|---|---|---|---|---|---|---|
| AWS EventBridge | Trigger | Yes | DIY | DIY | Per schedule | 14M/mo |
| Cloudflare Workers | Trigger | UTC | DIY | DIY | Undocumented | Yes |
| GitHub Actions | Trigger | Yes* | Logs | Via API | Manual | Free min |
| Google Cloud Scheduler | Trigger | Yes | Logs | DIY | Per job | 3 jobs |
| Vercel Cron | Trigger | UTC | DIY | DIY | None | 1/day |
| cron-job.org | Managed | Yes | Yes | Yes | None | Unlimited |
| EasyCron | Managed | Yes | Yes | Yes | None | 200/day |
| Posthook | Managed | Yes | Delivery log | Delivery only | Project + hook | 1K/mo |
| Runhooks | Managed | Yes | Yes | Yes | Per job | 2K/mo |
| Smpl Jobs | Managed | Yes | Yes | Yes | Named policies | 3K/mo |
| Upstash QStash | Managed | Yes | Logs only | Limited | Per schedule | ~1K/day |
✓ built in · ~ partial or workaround · ✗ build it yourself · *GitHub Actions added IANA timezones in March 2026.
Retries: where the products actually differ
The retries column deserves more than a checkmark, because “supports retries” hides four separate questions. Does it retry at all? Can you shape the retry — attempts, backoff, delays? Can you control the request timeout? And can you define what counts as success, so the thing knows when to retry?
The answers scatter. Three services don’t retry, full stop: Vercel says so outright (“Vercel will not retry an invocation if a cron job fails”), and cron-job.org and EasyCron simply run the job again at its next scheduled time — EasyCron will notify you about the failure, but it won’t retry it. Cloudflare’s docs don’t document retry behavior for cron triggers in either direction, which for planning purposes is the same as no. GitHub’s answer is a manual re-run button.
The two cloud schedulers do retry properly — EventBridge up to 185 retries with exponential backoff, Cloud Scheduler with a fully shapeable curve, up to 5 retries — but both hardwire what counts as retryable, and EventBridge’s HTTP path caps every request at a non-negotiable 5 seconds. Posthook lets you set a default policy per project and override it per hook, with backoff factors and jitter, against a fixed 10-second timeout. Runhooks configures attempts, delays, and multipliers per job, with plan-level caps on attempts. QStash goes as far as accepting a literal math expression for the retry delay.
Two details are rarer than they should be. Defining success: nearly everyone hardwires 2xx. EasyCron, of all things, is the only service here that can look inside the response body — it can match the body against a regexp and call a 200 a failure. Smpl Jobs works at the status level: each job declares which code or class counts as success, and each retry policy declares which statuses are worth retrying — 5xx but not 501, say. And reuse: everywhere else, retry settings live inline on each job. Smpl Jobs makes retry policies named, account-level resources — define “aggressive” once and reference it from all 81 of your jobs, instead of configuring it in 81 places. Posthook’s per-project default is the only other step in that direction.
Category 1: schedulers that trigger your code
AWS EventBridge Scheduler
EventBridge Scheduler is the most powerful option in the category, and effectively free: the free tier covers 14 million invocations a month, so a once-a-minute job won’t come close. The timezone support is real, daylight saving included. The thing to understand is what it does. EventBridge invokes a target — a Lambda function, a queue, a Step Function, or an HTTPS endpoint via an API destination. It will not call your URL and save what came back. For that you’ll wire up a Lambda to make the request and store the result, DynamoDB for the history, API Gateway to read it back, and CloudWatch for the logs. Good times. Best when you’re already on AWS, need to trigger AWS resources, or run at a scale where 14 million invocations is a number that matters.
Cloudflare Workers Cron Triggers
If you already deploy Workers, Cron Triggers are about as low-friction as scheduling gets: add a cron trigger and a scheduled() handler runs your Worker. The free tier is generous and it’s fast at the edge. It runs in UTC only, though, with no timezone handling, and you’ll build response capture and history yourself, usually on D1 or KV. Best when you already deploy Workers and your scheduling needs are simple and UTC-friendly.
GitHub Actions (scheduled workflows)
Scheduled workflows are free for small jobs, with no new infrastructure if the code already lives on GitHub. Scheduled workflows are known to run late under load — when we measured it, the median run was roughly 29 minutes late. And run history with captured responses means working through workflow logs and artifacts; there’s no clean executions endpoint. The old UTC-only limitation is gone, at least: since March 2026 you can attach an IANA timezone to a schedule trigger. It’s a CI tool that happens to have a timer. Best when the task is CI-adjacent and occasional, and exact timing doesn’t matter.
Google Cloud Scheduler
Cloud Scheduler is Google’s managed cron, and it’s priced by an unusual meter: you pay per job definition — $0.10 a month each, first three free per billing account — and executions cost nothing, so a job can fire every minute all month for a dime. Timezone support is full IANA with daylight saving observed, retries — once you turn them on — get proper exponential backoff, and it carries a financially backed SLA (99.5%). It will happily call any public URL, but it keeps nothing your endpoint says: each run writes start and finish entries to Cloud Logging, the HTTP status code surfaces only in the failure text, and there’s no executions API — reading run history means querying Cloud Logging yourself. Best when you’re already on Google Cloud and want an SLA-backed trigger for Cloud Run, Pub/Sub, or a public URL, and don’t need to know what the endpoint said back.
Vercel Cron Jobs
Vercel Cron Jobs are the least effort of anything here if your app is already on Vercel, because a cron job is just one of your routes invoked on a schedule. The catches all live on the free Hobby plan: you get one run per day, and even that is approximate. A job set for 1:00 can fire anywhere in the following hour. Per-minute schedules need the Pro plan, about $20 a month. Schedules run in UTC, and capturing and querying history is on you. Best when you’re on Vercel, a once-a-day trigger is enough, and you’d rather not add another vendor.
Category 2: managed cron-as-a-service
cron-job.org
cron-job.org has been running for over 15 years and is still genuinely free: unlimited jobs down to once a minute, timezone support, response headers and body saved for each execution, run-now testing, and a REST API for managing jobs and reading history, which is more than a free service has any right to include. The fine print: captured headers and bodies are kept for 2 days, history is the last 50 executions per job, requests time out at 30 seconds, and it’s a community-funded project with no formal SLA — fine for personal and non-critical jobs, less comfortable where a missed run costs money. Best when you want a free, no-friction way to ping a URL and see recent responses.
EasyCron
EasyCron is one of the longest-running services in the category. It supports per-job timezones, execution logging with separate failure logs, and a REST API for jobs and logs. The free plan allows up to 200 executions a day with a 20-minute minimum interval; paid plans start around $24 a year and unlock one-minute intervals and higher volumes. The interface is dated and utilitarian. Best when you have a modest number of URL-pinging jobs and want a proven, no-surprises service.
Posthook
Posthook is the specialist of the group: it schedules webhooks back to your own endpoints — reminders, follow-ups, expirations — rather than general-purpose cron. One-off hooks schedule to the second in any IANA timezone, with daylight-saving edge cases actually documented; recurring schedules come from a fixed menu of intervals (every 5 minutes at the tightest) rather than cron expressions, and each project is pinned to one domain, with the per-hook target given as a path. Retries are serious and configurable, there are SDKs for TypeScript, Python, and Go plus a CLI and config-as-code, and it’s been run by the same solo founder since 2018, claiming 99.98% uptime along the way. What it deliberately doesn’t do is remember what your endpoint said: hook history records delivered-or-failed, attempts, and timing — not the response. The free tier is 1,000 hooks a month with 7-day history; paid starts at $39 a month. Best when your app needs “call me back at 4:07pm Tuesday, their time” at scale, and the response can stay your problem.
Runhooks
Runhooks is the newest thing on this list by a wide margin — its terms page went up in April 2026 — and on paper it covers the full category-2 checklist: cron schedules with IANA timezones (or fixed intervals), response status and body captured for every run, a REST API for run history, replay of failed executions, and retries with exponential backoff — up to 10 on the top plan; the free tier caps at 3. The fine print is mostly retention and caps: the homepage’s “up to 30 days” of logs belongs to the $129 plan — the free tier keeps them for 24 hours, allows 3 jobs and 2,000 runs a month (capped at 200 a day), and times requests out at 30 seconds. Paid starts at $19 a month. There’s no SLA, and no named company behind the product. Best when you want cheap, API-first scheduled HTTPS calls with short-lived response logs, and you’re comfortable betting on a very young service.
Smpl Jobs
This one’s mine, so apply the appropriate discount. Smpl Jobs is managed cron-as-a-service with the second-category checklist built in: timezone-aware cron schedules plus one-off and manual jobs, response capture (status, headers, and body, with truncation flagged), a REST API for listing and fetching past runs, and a run-on-demand action so you can fire a job right now and read the real response before trusting it on a schedule. The free tier is 3,000 runs a month across 10 jobs, with 30 days of run history, a 30-second request timeout, and responses captured up to 64 KiB. There are SDKs in six languages, a CLI, a Terraform provider, and an MCP server. We’re the newest entrant in the category; the veterans above have longer track records.
Upstash QStash
QStash approaches the job from the delivery side: it gets HTTP requests to your endpoints reliably, with automatic retries, a dead-letter queue, delays, and callbacks. It supports cron schedules with timezones (CRON_TZ=America/New_York 0 4 * * *), the free tier covers around 1,000 messages a day, and the SDKs are clean. It sits in this category on a technicality, though. QStash delivers messages; what your endpoint said in response is kept briefly for logging and debugging, and there’s no queryable archive of captured bodies. Your endpoint also has to be publicly reachable, which means a tunnel for local development. Best when you need durable, retrying delivery to serverless or edge endpoints more than you need response history.
Environments, and who gets to touch production
Enterprise delivery has a shape: the same job runs in development, then staging, then production — same definition, different endpoint per environment — and not everyone who can edit the staging copy is allowed anywhere near the production one. If that’s your world, this section is the real comparison.
The cloud platforms solve it the cloud way: an account or project per environment, and IAM to divide the writers. EventBridge schedules can be grouped and IAM-scoped so a principal may write schedule/staging/* but not schedule/prod/*; Google’s answer is a project per environment. It works and it’s auditable — and the “same job” becomes N copies you promote by pipeline. GitHub is the interesting case: Environments with required reviewers gate jobs at run time, but a scheduled job pointed at a reviewer-protected environment waits for a human on every tick, which makes protection and unattended scheduling mutually exclusive. Cloudflare has genuine per-environment Workers (and per-environment crons) via Wrangler, but its roles are account-scoped: anyone who can edit staging can edit production. Vercel runs crons against production only; the effective gate is who can produce a production deployment.
The managed camp mostly doesn’t play. cron-job.org is a single-user account with folders. EasyCron’s Enterprise plans add subusers, but a subuser who can edit anything can edit everything. Runhooks has no teams at all. Posthook and Upstash have teams with roles, but the roles span the whole account — “staging-write, production-read” isn’t expressible in either.
Smpl Jobs models this directly: a job is one definition with per-environment overrides — a different URL, schedule, timeout, or retry policy per environment, everything else inherited — and role-based access with environment access groups, so a member’s write access can cover development and staging and stop at production. As far as I can tell, that combination — one job, per-environment variants, environment-scoped write permission — doesn’t exist anywhere else in the managed category. If you don’t run environments, none of this matters. If you do, it’s the first thing to check, and the table has no column for it because almost every cell would be empty.
Which should you pick?
- Already on AWS, triggering AWS resources, or running at large scale → EventBridge Scheduler. An enormous free tier and more power than anything else here; you build the capture-and-history layer yourself.
- Already on Google Cloud → Cloud Scheduler. Per-job pricing that rounds to zero, a real SLA, and Cloud Logging as your history — such as it is.
- Your app is on Vercel or Cloudflare, the cadence is coarse, and UTC is fine → their native cron. One less vendor.
- The task is CI-adjacent and occasional → GitHub Actions. Free if the code already lives there; just don’t expect punctuality.
- You want a free, no-friction way to ping a URL and see recent responses → cron-job.org. Hard to beat for personal and non-critical jobs.
- A modest number of URL-pinging jobs on a proven, no-surprises service → EasyCron. The interface is dated; the track record isn’t.
- You need one-off callbacks at exact local times — reminders, follow-ups, expirations → Posthook. Purpose-built for exactly that; it just won’t remember the response.
- You need durable, retrying delivery to serverless or edge endpoints → QStash. Just don’t ask it to be your run archive.
- You want response capture, run history, and timezone cron as one managed product → Smpl Jobs or Runhooks.
- The same job promoted through dev, staging, and production, with production locked down → Smpl Jobs — or a cloud scheduler with an account (or schedule group) per environment and IAM.