I recently built a small Flask backend for a side project. I deployed it on Render’s free tier, got that shiny HTTPS URL, and felt that classic developer rush of seeing my code live.
Proud of my work, I sent the link to a friend for feedback.
His response? "Bro, it's not loading."
I clicked the link myself. It did load, but only after staring at a blank screen for nearly a full minute. If you've ever deployed a passion project, you know that a 60-second loading screen is an absolute conversion killer.
Here is exactly why that happened, and how I fixed it permanently without spending a single dime.
The Problem: Render’s Free Tier "Cold Start"
After some digging, I realized this wasn't a bug—it’s a feature of Render’s free tier.
To save server resources, Render automatically spins down your service if it receives zero traffic for 15 minutes. When a new request finally comes in, the server has to boot back up before it can process anything. This "cold start" can take anywhere from 30 to 60 seconds.
If I'm testing the API from my laptop, I know what's happening. But to a real user opening the link cold, the site just looks broken.
Since the project was in its early stages, I didn't want to shell out money for a paid hosting plan yet. But I also needed my app to be snappy. I needed a workaround.
My First Thought: GitHub Actions (And Why It Failed)
My immediate instinct was to write a quick GitHub Actions cron job. The logic was simple: ping the server with a curl request every 14 minutes. If the server keeps getting hit before the 15-minute timer runs out, it never falls asleep.
on:
schedule:
- cron: '*/14 * * * *'
jobs:
ping:
runs-on: ubuntu-latest
steps:
- run: curl https://green-spoon-backend.onrender.com/api/health
Then I did the math.
GitHub gives you 2,000 free Actions minutes per month. Pinging the server every 14 minutes equals roughly 103 runs per day—which comes out to over 3,000 runs per month. That completely blows past the free limit. I definitely didn't want a surprise bill for a side project, so I scrapped the idea.
The Ultimate Fix: UptimeRobot
The core concept was still solid: I needed a tool to automatically ping the server. I just needed one that did it for free.
Enter UptimeRobot.
UptimeRobot is a standard website monitoring service. You give it a URL, and it checks it periodically to ensure your site is online. The best part? Their free plan allows checks every 5 minutes—more than frequent enough to keep a Render instance wide awake.
Step 1: Create a Lightweight Endpoint
Before setting up the monitor, I didn't want to ping my root / route. Root routes often trigger heavier logic or database calls, which is a waste of resources.
Instead, I added a dead-simple /health endpoint to my Flask app:
@app.route('/health')
def health():
return {"status": "ok"}, 200
There are no database queries and no heavy business logic here. It just returns a 200 OK status confirming the server is alive. (Pro tip: Having a health check endpoint is a standard best practice in backend engineering anyway!)
Step 2: Set Up the Ping
- I went to UptimeRobot and made a free account.
- I created a new HTTP monitor.
- I pointed it to my new endpoint: https://green-spoon-backend.onrender.com/api/health
- I set the check interval to 5 minutes.
It took me less than two minutes to set up, and my Flask server hasn't fallen asleep since.
Won't I Get Spammed with Emails?
This was my biggest worry. I didn't want an email hitting my inbox every 5 minutes saying, "Hey, your site is still up!"
Thankfully, that’s not how UptimeRobot works. The pings happen silently in the background. You only ever get an email if your server actually goes down, and another when it comes back online. You get the benefit of keeping your server awake, bundled with professional-grade uptime monitoring for free.
Have you run into the free-tier sleep issue before? If you have a different setup or a cool alternative tool you use to keep your side projects awake, drop it in the comments below!
Top comments (0)