How to Keep Free-Tier Apps Awake (Render, Railway, Fly.io & Co.)

Free hosting tiers put your app to sleep after 15 minutes of inactivity, causing 30-60 second cold starts. Here's how keep-alive pings fix it — and how to set one up in two minutes.

You deployed your side project on a free tier, sent the link to a friend, and the first thing they saw was… a loading spinner for 45 seconds. Not a great first impression for something you spent weekends building.

This isn't a bug in your app. It's how free hosting tiers work — and it has a two-minute fix.

Why free-tier apps go to sleep

Free plans on most platforms-as-a-service spin your app down after a period of inactivity, typically around 15 minutes without an incoming request:

From the platform's perspective this is fair — they can't run every hobby project 24/7 for free. From your visitor's perspective, your site is just slow, and they won't wait to find out why. If the sleeping service is an API consumed by a frontend, the first request often doesn't just lag — it times out and errors.

The fix: keep-alive pings

The workaround is almost embarrassingly simple: if inactivity causes sleep, schedule activity. An HTTP request to your app every 10–14 minutes resets the idle timer, and the platform never puts it to sleep.

You need three things:

  1. A lightweight endpoint to hit
  2. Something that calls it on a schedule, from outside your app
  3. Ideally, an alert if the ping starts failing — because now you have uptime monitoring for free

1. Add a health endpoint

Don't ping your homepage — it drags in database queries and rendering you don't need. A tiny health route is enough to keep the process warm:

// app/api/health/route.ts (Next.js example)
import { NextResponse } from "next/server";

export async function GET() {
  return NextResponse.json({ ok: true, ts: Date.now() });
}

Any framework equivalent works — an Express /healthz route, a Flask /ping, whatever returns a fast 200.

2. Schedule the ping — from outside

This is the part people get wrong: the pinger cannot live inside the app it's keeping awake. A setInterval in your own process dies the moment the process sleeps — the very thing it was supposed to prevent. The scheduler must be external.

With CronSpark, the whole setup is one job — there's a ready-made Keep Alive template, so it's genuinely two minutes:

  1. Create a job from the Keep Alive template
  2. Paste https://yourapp.onrender.com/api/health
  3. Set the interval to every 10 minutes (safely under Render's 15-minute idle window)

That's it. The free plan covers this use case — keep-alive pings for a couple of side projects is exactly what 5 free jobs are for.

3. The part most guides skip: you now have monitoring

Here's the underrated bonus. A dumb pinger keeps your app awake; a monitoring pinger also tells you when your app stops answering.

Every CronSpark keep-alive run is logged with its status code and response time, and if your endpoint starts returning 500s or timing out, you get an alert on email (or Discord, Slack, Telegram on Pro) — the moment it happens, not when a user complains. Your keep-alive ping quietly doubles as uptime monitoring.

You can even go a step further and add a response pattern match — for example, expect the body to contain "ok":true. Then you're alerted not just when the app is down, but when it's up-but-broken.

Things to keep in mind

Summary

Free tiers sleep after ~15 minutes of inactivity; a scheduled external ping every 10 minutes keeps them awake. Use a dedicated health endpoint, never schedule the ping from inside the app itself, and pick a pinger that alerts you on failure — that way the same job that kills your cold starts is also the monitor that tells you your project is down. CronSpark's Keep Alive template sets the whole thing up in about two minutes.