A production-ready Cloudflare Worker that automatically pings your Render applications every 14 minutes during business hours (7 AM - 12 PM IST) to prevent them from going to sleep on the free tier.
The Challenge: Render's free tier puts applications to sleep after 15 minutes of inactivity, resulting in cold starts and slow response times for users.
The Solution: This intelligent worker pings your application every 14 minutes during peak business hours, ensuring optimal availability when your users need it most while conserving resources during off-peak times.
- π Zero Cost - Runs entirely on Cloudflare's generous free tier
- β° Smart Scheduling - Active only during business hours (7 AM - 12 PM IST)
- π‘οΈ Production Ready - Comprehensive error handling, retry logic, and timeout protection
- π Detailed Monitoring - Rich logging and status endpoints for observability
- π§ Zero Maintenance - Set once, runs automatically
- β‘ Quick Deploy - Ready in under 5 minutes
- π Configurable - Customizable endpoints, timeouts, and schedules
# Clone the repository
git clone https://github.com/kavinthangavel/cloudflare-render-ping.git
cd cloudflare-render-ping
# Install dependencies
npm install
# Install Wrangler CLI (if not already installed)
npm install wrangler --save-dev
# Login to Cloudflare (opens browser for authentication)
npx wrangler login
# Set your Render application URL as a secret
npx wrangler secret put RENDER_APP_URL
# When prompted, enter: https://your-app.onrender.com
# Deploy the worker to Cloudflare
npx wrangler deploy
# Your worker will be available at:
# https://render-ping-worker.your-subdomain.workers.dev
# Test the worker manually
curl https://your-worker.workers.dev/ping
# View real-time logs
npx wrangler tail
# Check configuration
curl https://your-worker.workers.dev/debug
Here are all the commands used during development and deployment:
# Authentication
npx wrangler login # Login to Cloudflare
npx wrangler whoami # Check current user
# Secrets Management
npx wrangler secret list # List all secrets
npx wrangler secret put RENDER_APP_URL # Set application URL
npx wrangler secret delete {SECRET_NAME} # Remove a secret
# Deployment
npx wrangler deploy # Deploy to production
npx wrangler deploy --dry-run # Preview deployment
npx wrangler deploy --name custom-name # Deploy with custom name
# Monitoring & Debugging
npx wrangler tail # View real-time logs
npx wrangler tail --format pretty # Formatted log output
npx wrangler dev # Run locally for development
# Configuration
npx wrangler generate --template worker # Generate new worker
npx wrangler init # Initialize new project
# Test endpoints
curl https://your-worker.workers.dev/ # Status page
curl https://your-worker.workers.dev/ping # Manual ping
curl https://your-worker.workers.dev/debug # Debug info
# Test with PowerShell (Windows alternative)
Invoke-RestMethod -Uri "https://your-worker.workers.dev/ping"
Invoke-WebRequest -Uri "https://your-worker.workers.dev/" | Select-Object Content
Variable | Required | Default | Description |
---|---|---|---|
RENDER_APP_URL |
β | - | Your Render application URL |
HEALTH_ENDPOINT |
β | /healthz |
Health check endpoint path |
TIMEOUT_MS |
β | 30000 |
Request timeout (milliseconds) |
RETRY_ATTEMPTS |
β | 2 |
Number of retry attempts |
# Required: Set your Render app URL
npx wrangler secret put RENDER_APP_URL
# Optional: Customize health endpoint
npx wrangler secret put HEALTH_ENDPOINT
# Enter: /api/health (or your preferred endpoint)
# Optional: Increase timeout for slow apps
npx wrangler secret put TIMEOUT_MS
# Enter: 60000 (for 60 seconds)
# Optional: Adjust retry attempts
npx wrangler secret put RETRY_ATTEMPTS
# Enter: 3 (for 3 retry attempts)
Edit wrangler.toml
to modify the ping schedule:
[triggers]
# Current: Every 14 minutes, 7 AM - 12 PM IST
crons = ["*/14 1-6 * * *"]
# Examples:
# Every 14 minutes, 24/7
crons = ["*/14 * * * *"]
# Every 15 minutes, weekdays only, 9 AM - 5 PM UTC
crons = ["*/15 9-17 * * 1-5"]
# Every 5 minutes, business hours extended
crons = ["*/5 0-8 * * *"] # 5:30 AM - 1:30 PM IST
Endpoint | Method | Description | Example Response |
---|---|---|---|
/ |
GET | Status dashboard | HTML page with configuration |
/ping |
GET/POST | Manual health check | {"success": true, "message": "Health check triggered"} |
/debug |
GET | Environment variables | {"environment_variables": {...}} |
# Real-time log monitoring
npx wrangler tail --format pretty
# Check worker analytics (in dashboard)
# Visit: https://dash.cloudflare.com/workers
# Test all endpoints
curl https://your-worker.workers.dev/
curl https://your-worker.workers.dev/ping
curl https://your-worker.workers.dev/debug
π Starting health check
- Worker initiatedβ Health check successful!
- Successful ping with response timeβ οΈ Server responded but status unclear
- Response received but unexpected formatβ HTTP Error: XXX
- Server returned error statusβ±οΈ Request timeout
- Request exceeded timeout limitπ Network error
- Connection or DNS issuesπ All attempts failed
- All retries exhausted
Add a health check endpoint to your Render app for optimal monitoring:
app.get('/healthz', (req, res) => {
res.status(200).json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
from datetime import datetime
import psutil
@app.route('/healthz')
def health_check():
return {
'status': 'ok',
'timestamp': datetime.now().isoformat(),
'uptime': time.time() - psutil.boot_time(),
'memory': psutil.virtual_memory()._asdict()
}
from datetime import datetime
from fastapi import FastAPI
@app.get("/healthz")
async def health_check():
return {
"status": "ok",
"timestamp": datetime.now().isoformat(),
"service": "My Render App"
}
If you don't want to add a dedicated health endpoint:
# Use homepage
npx wrangler secret put HEALTH_ENDPOINT
# Enter: /
# Use existing API endpoint
npx wrangler secret put HEALTH_ENDPOINT
# Enter: /api/status
# Problem: Worker shows "Not configured"
# Solution: Set the secret properly
npx wrangler secret put RENDER_APP_URL
# Enter your full Render URL: https://your-app.onrender.com
# Verify it was set
npx wrangler secret list
# Problem: "No fetch handler" error
# Solution: Check your main entry point in wrangler.toml
# Ensure: main = "src/index.js"
# Problem: Wrangler login issues
# Solution: Clear auth and re-login
npx wrangler logout
npx wrangler login
# Problem: "All attempts failed"
# Solution: Test your Render URL manually
curl https://your-app.onrender.com/healthz
# If 404, try homepage instead
npx wrangler secret put HEALTH_ENDPOINT
# Enter: /
# Check deployment status
npx wrangler tail
# Verify cron schedule is correct
Get-Content wrangler.toml
# Test manual trigger
curl https://your-worker.workers.dev/ping
# Check worker configuration
curl https://your-worker.workers.dev/debug
# View deployment info
npx wrangler dev --local-protocol https
# Check if secrets are set
npx wrangler secret list
# Test Render app directly
curl https://your-app.onrender.com/healthz -v
- β 100,000 requests/day included
- β ~103 requests/day used (7Γ14.7 pingsΓ5 weekdays)
- β Completely free for this use case
- β 10ms CPU time per request (well under 10,000ms limit)
- β 750 hours/month of runtime
- β Stays awake during business hours only
- β Sleeps at night to conserve hours
- β No additional costs
- Cron Trigger - Cloudflare's scheduler activates worker every 14 minutes
- Environment Check - Worker validates configuration
- Health Request - GET request sent to your Render app
- Response Validation - Check for successful response
- Retry Logic - Automatic retries on failure
- Logging - Detailed logs for monitoring
- Completion - Process repeats next cycle
# Edit the worker code
code src/index.js
# Update configuration
code wrangler.toml
# Deploy changes
npx wrangler deploy
# View updated logs
npx wrangler tail
# Deploy to a staging environment
npx wrangler deploy --name render-ping-staging
# Test staging
curl https://render-ping-staging.your-subdomain.workers.dev/ping
# Deploy to production when ready
npx wrangler deploy
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Commit changes:
git commit -m 'Add amazing feature'
- Push to branch:
git push origin feature/amazing-feature
- Open a Pull Request
π― Ready to keep your Render app alive? Follow the Quick Start guide above!