Holding The Load
A simple and smart way to manage busy times for your web apps, built on Cloudflare. It protects your server from getting overwhelmed by too many requests at once, like a traffic jam controller for the internet.
This project helps keep your affordable server (VPS) safe from sudden spikes in webhook requests, preventing crashes and keeping things running smoothly.
When Should You Use It?
- Automation Tools: Like N8N or similar, where you need to handle events from other services.
- Self-Hosted Workflows: For engines that react to webhook events.
- APIs: Any app that receives notifications or data pushes.
- AI Agents: Bots or assistants that res…
Holding The Load
A simple and smart way to manage busy times for your web apps, built on Cloudflare. It protects your server from getting overwhelmed by too many requests at once, like a traffic jam controller for the internet.
This project helps keep your affordable server (VPS) safe from sudden spikes in webhook requests, preventing crashes and keeping things running smoothly.
When Should You Use It?
- Automation Tools: Like N8N or similar, where you need to handle events from other services.
- Self-Hosted Workflows: For engines that react to webhook events.
- APIs: Any app that receives notifications or data pushes.
- AI Agents: Bots or assistants that respond to events via webhooks.
Why Use It? Benefits
- Handles Busy Times: Webhook spikes are managed before they reach your server, so it stays stable.
- Predictable Workload: Your server runs smoothly without surprises.
- Save Money: No need to pay for extra power all the time—just when you need it.
- No Lost Data: Even if your server goes down temporarily, webhooks are safely stored and not lost.
Get Help
Stuck setting this up? Or having issues with your app?
Email me: tiagorosadacost@gmail.com
Table of Contents
- What is This?
- When to Use It
- Benefits
- Key Features
- Cost Estimate
- Tech Behind It
- Getting Started
- Settings
- Free Plan Limits
- How It Works
- Examples
- Testing
- Get Help
What is This?
This tool uses Cloudflare’s powerful infrastructure (like smart workers and reliable storage) to handle sudden rushes of requests. You can process them one at a time or in small groups, at your own speed.
When to Use It
Picture this: You’re running an app on a budget server that’s not super powerful—because powerful ones cost more. As your app or chatbot gets popular, it starts getting tons of requests all day, overloading the server. You have to upgrade to a bigger, more expensive server, and if it gets even busier, you upgrade again... and again.
Holding The Load solves this! Cloudflare takes care of the busy times and unexpected traffic, while you pull in requests at a pace that matches your server’s strength.
Key Features
- Smart Queuing: Lines up incoming requests during busy periods so nothing gets missed.
- Flexible Processing: Pull requests one by one or in batches (like 10 at a time).
- Group Organization: Separate webhooks by app or task. (To add your own groups, edit the
groups.jsonfile in the project root.) - Reliable Storage: Uses advanced storage to keep data safe.
- Budget-Friendly: Low cost for handling traffic bursts.
- Duplicate Prevention: Stops the same request from being processed twice.
- Data Checking: Validates incoming requests based on your group settings.
Setting Up Groups
- Open the
groups.jsonfile. - Add a new name to the list. (Use simple names without special characters, like
user_queue,product_updates,chatbot_support.)
Setting Up Data Validation
- Take the JSON structure you expect for your data.
- Go to this website and paste your JSON.
- It will create a simple code snippet.
- Copy the part that looks like
z.object({...}). - Open
src/schemas-validation.tsand add your group name as a key, with the copied code as the value. - Now, when webhooks come in for that group, they’ll be checked automatically.
Cost Estimate
Example: 10 million requests per month, using Cloudflare’s services.
Breakdown
| Part | Details | Monthly Cost |
|---|---|---|
| Basic Plan | Cloudflare Workers Paid Plan | $5.00 |
| Requests | 10M (included) | $0.00 |
| Processing Time | Extra time beyond free | $0.80 |
| Storage Requests | 10M | $0.50 |
| Storage Writes | 500k (included) | $0.00 |
| Storage Reads | Based on your setup (included) | $0.00 |
| Total | $6.30 |
Tech Behind It
- Cloudflare Workers (handles the heavy lifting)
- Durable Objects with SQLite (safe data storage)
- Node.js (v21.0.0) and TypeScript (for coding)
Getting Started
- Download the Project: Clone it to your computer.
- Set Up Security: Add your
API_KEYinwrangler.jsonc. - Test Locally: Run
npm run devto try it on your machine. - Go Live: Run
npm run deployto put it on Cloudflare (needs Wrangler CLI). - Test the Routes: Import
Insomnia_2026-01-12.yamlinto Insomnia to test. - Keep It Healthy: Set up a schedule to call
/healthevery minute to save data safely.
Settings
API_KEY: A secret key to protect your app—only authorized apps can send requests.
Free Plan Limits
The free plan has some limits:
- 100,000 requests per day
- 128MB storage memory
- 1,000 requests per minute
- 100,000 data writes per day
Need More?
Upgrade to the $5 plan for more power. Check Cloudflare Pricing.
How It Works
Examples
Sending a Webhook
Request:
curl --request POST \
--url http://localhost:8787/new-events \
--header 'Content-Type: application/json' \
--header 'x-api-key: your_api_key' \
--data '{
"message": "Hello from user 123",
"timestamp": "1751872147530"
}'
Response:
{
"ok": true
}
Getting Webhooks to Process
Request:
curl --request GET \
--url 'http://localhost:8787/pull-events?total=1' \
--header 'Content-Type: application/json' \
--header 'x-api-key: your_api_key'
Response (with data):
[
{
"id": "unique-id-here",
"requestBody": {
"message": "Hello from user 456",
"timestamp": "1793123847723"
},
"retries": 0
}
]
Response (nothing to process):
[]
Testing
We tested with 5,000 requests from 600 fake users using a tool called autocannon. Here are the results:
┌─────────┬────────┬────────┬─────────┬─────────┬───────────┬──────────┬─────────┐
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │
├─────────┼────────┼─────────┼─────────┼─────────┼───────────┼──────────┼─────────┤
│ Latency │ 150 ms │ 214 ms │ 1941 ms │ 2002 ms │ 434.97 ms │ 497.2 ms │ 2345 ms │
└─────────┴────────┴────────┴─────────┴─────────┴───────────┴──────────┴─────────┘
┌───────────┬─────┬──────┬────────┬─────────┬────────┬────────┬────────┐
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │
├───────────┼─────┼──────┼────────┼─────────┼────────┼────────┼────────┤
│ Req/Sec │ 0 │ 0 │ 821 │ 2,307 │ 1,250 │ 901.49 │ 821 │
├───────────┼─────┼──────┼────────┼─────────┼────────┼────────┼────────┤
│ Bytes/Sec │ 0 B │ 0 B │ 505 kB │ 1.42 MB │ 769 kB │ 555 kB │ 505 kB │
└───────────┴─────┴──────┴────────┴────────┴────────┴────────┘