Build and Host Full-Stack App with Database for Free
Published on: 10/4/2025
I have earlier described how to build a full-stack edge app. It used only soft guardrails to enforce usage limits, however. In this guide I will describe how to enforce usage limits on the server-side using Cloudflare (CF) D1 database.
Edge Full-Stack App with D1 Rate Limits
Understanding Cloudflare D1
Cloudflare D1 is a serverless SQLite-compatible database (DB) designed for edge computing environments. It offers horizontal scaling across multiple databases, built-in disaster recovery, and seamless integration with Cloudflare Workers.
Cloudflare D1 usage limits on the Workers Free plan are as follows:
Maximum storage per database: 500 MB
Maximum total storage per account: 5 GB across all databases
Maximum number of databases per account: 10
Daily rows read limit: 5 million rows
Daily rows written limit: 100,000 rows
Queries per Worker invocation (read subrequest limits): 50
Time Travel (point-in-time recovery) duration: 7 days
Maximum database size and rows per table are within the above storage limits, with unlimited rows per table constrained by storage size
If you exceed these limits, queries will return errors until usage resets at midnight UTC; storage limits require cleanup before further data inserts/alterations. Upgrading to a paid plan removes or significantly raises these quotas.
These limits allow prototyping and moderate usage of D1 on the free tier while incurring no charges, with daily limits resetting every day at midnight UTC
Create D1 DB
In CF sidebar find "Storage & Databases" -> "D1 SQL-database" -> "Create Database"


Call it e.g. "rate-limiter-db" (name is not important though)
Updated worker code
Update the worker we created earlier with the code from my GitHub repo .

Again the code for the updated worker is here: https://github.com/ZeroCostStartup/llama-chat/blob/main/worker-with-db.js
It will create two tables in the D1 and will be adding timed user origin IP.
IMPORTANT! Just as before change PAGES_ORIGIN
to your actual pages URL in worker's code.
Bind D1 DB to your worker
Finally, make a bining on your worker page

Proceed to "Add binding" then you will be prompted to name the variable that will be bownd to D1 DB.
IMPORTANT! It must be called RATE_LIMITER
or you would need to update this variable in worker's code

The chose the database this RATE_LIMITER var is to be connected. Just start typing the name of your D1 DB in "D1 database" input field. Then click "Add binding".
This is essentially it.
You can go back to D1 settings, visualize the tables by clicking "Explore Data":

There are two tables that you can also explore and change the hard usage limit:

Please note that these guardrails have one important limitation. Some users can employ multiple IPs to abuse you website but this is rare.