
A note from the founder. Tired of Lambda cold starts but not the provisioned-concurrency bill? I'm looking for a small group of early users to try Runhooks and share honest feedback. Early adopters get upgraded plans for free.
Your Lambda-backed API is quick — until the first call after a quiet period. That one takes a second or two longer than the rest, sometimes enough to trip a client timeout. Call it again and it's snappy.
That first slow call is a cold start, and AWS's official fix for it — provisioned concurrency — solves the latency but adds a bill you may not want for a low-traffic function.
Why Lambda Cold Starts Happen
Lambda runs your code in an execution environment that AWS creates on demand. When a function goes idle, AWS reclaims that environment. The next invocation has to build a new one: download your deployment package, start the runtime, and run your initialization code (imports, SDK clients, database connections) before your handler even begins.
That setup is the cold start. It's most painful for:
- Functions in a VPC, which historically pay extra for network setup.
- Large dependency bundles, which take longer to load.
- JVM and .NET runtimes, which have heavier startup than Node.js or Python.
AWS's answer is provisioned concurrency: keep a set number of environments initialized and ready at all times. It delivers consistent low latency — and it bills you to keep those environments warm continuously, whether or not anyone is calling. For a function that's idle most of the day, that's paying full-time to fix an occasional delay.
The Fix: A Scheduled Warm-Up Invocation
There's a lighter approach: invoke the function yourself on a schedule so AWS keeps at least one environment warm between real requests.
Most Lambda functions sit behind an API Gateway route or a Function URL. Point a scheduled GET at a lightweight health path:
export const handler = async (event) => {
// A cheap path that skips the real work when it's just a warm-up.
if (event.rawPath === '/health' || event.warmup) {
return { statusCode: 200, body: 'ok' };
}
// ... real handler logic
};
Then schedule that request every 5 minutes (*/5 * * * *). Each invocation keeps an execution environment alive, so the next real caller lands on a warm function instead of paying the cold-start tax — and you only pay for a handful of short pings an hour, not a continuously provisioned environment.
Why a DIY Cron Job Isn't Enough
You could schedule the ping with a cron job, or even an EventBridge rule. Both have gaps:
- A laptop or VPS cron job stops when the machine sleeps, and means running a server to keep your serverless function warm.
- Fails silently. If a warm-up call errors, there's no retry, no alert, no log — the environment goes cold and the next user notices.
- No unified execution history. Correlating a slow request with a missed warm-up means digging through scattered logs.
- No retries. A single dropped ping can be the gap where the environment is reclaimed.
You can bolt retries, logging, and alerting onto a curl or a Lambda-invoking script — but at that point you've rebuilt a scheduler.
How Runhooks Keeps Lambda Warm
Runhooks is a scheduled HTTP execution service with reliability built in. Warming a function is a two-minute setup:
- Create a job — name it "Lambda keep-warm."
- Set the URL — your API Gateway or Function URL health path, e.g.
https://abc123.execute-api.us-east-1.amazonaws.com/health. - Set the schedule —
*/5 * * * *. - Enable retries — 3 attempts with exponential backoff.
What you get beyond a bare cron job or EventBridge rule:
- Execution logs — every warm-up recorded with status, response, and duration.
- Automatic retries — a transient failure retries instead of leaving the function to go cold.
- Failure alerts — if the function starts erroring, you're notified immediately.
- Managed infrastructure — runs 24/7, independent of your own machines.
Because each ping is logged and alertable, you get keep-warm and uptime monitoring in one job: the invocations keep an environment ready, and the alerts catch a genuinely broken function rather than just a cold one.
When Provisioned Concurrency Is Still Worth It
To be fair, warming isn't a total replacement. If you need guaranteed zero cold starts under load — a high-traffic, latency-critical API where a burst of concurrent requests must all be fast — provisioned concurrency pre-initializes the environments a warm-up ping can't. A single warm environment handles the trickle after it; it doesn't pre-warm the extra environments Lambda spins up when concurrency spikes.
Use a scheduled warm-up when you want to kill the idle cold start on a low-traffic function without paying to keep environments provisioned around the clock. Reach for provisioned concurrency when consistent latency at scale is a hard requirement.
Get Started
Lambda's pay-per-use model is great for cost — cold starts are the trade-off, and you can soften them cheaply:
- Add a lightweight health path to your function.
- Try Runhooks and schedule a
GETevery 5 minutes. - Callers hit a warm function, and you get alerted if it starts failing.
Preview your schedule with the cron expression visualizer, and compare plans when you need more jobs or longer log retention.
Frequently Asked Questions
Why does AWS Lambda have cold starts?
When a Lambda function hasn't been invoked recently, AWS tears down its execution environment. The next invocation has to create a fresh environment — download your code, start the runtime, and run any initialization — before your handler runs. This adds latency, and it's worst for functions in a VPC, with large dependency bundles, or on JVM and .NET runtimes.
How do I keep a Lambda function warm?
Invoke the function on a schedule so AWS keeps its execution environment alive between real requests. A warm-up invocation every 5 minutes is the common interval. You can trigger it by calling the function's API Gateway URL or Function URL on a schedule with an external scheduler like Runhooks, which also retries failed pings and alerts you when the function errors.
Is a warm-up ping cheaper than provisioned concurrency?
For low-traffic functions, yes. Provisioned concurrency bills you to keep a set number of environments initialized around the clock. A warm-up ping only pays for a short invocation every few minutes, which is far cheaper for functions that are idle most of the time. Provisioned concurrency is still the right tool when you need guaranteed zero cold starts at scale.
Does pinging a Lambda eliminate all cold starts?
It keeps one execution environment warm, which removes the cold start for the steady trickle of traffic that follows. It does not remove cold starts that happen when many requests arrive at once and Lambda spins up additional concurrent environments. For that, provisioned concurrency is the answer. For most low-traffic APIs and webhooks, a single warm environment covers it.
Read next: Preventing Cloud Run Cold Starts · Eliminating Render Free Tier Cold Starts · Preventing Fly.io Machines From Stopping · Scheduled HTTP Requests vs. Cron Jobs