Your own 404less, on Cloudflare’s free tier.
Everything runs in one Worker with D1 (SQLite), Durable Objects and two cron triggers. All of it is on the Workers Free plan, so a personal instance costs nothing at hobby scale.
-
Cloned
-
Provisioned
-
Live
https://404less.you.workers.dev
One-click deploy
The Deploy to Cloudflare button clones the repository into your GitHub account and
provisions the D1 database and the Durable Objects declared in
wrangler.jsonc. Migrations and the dashboard build run as part of the deploy.
When it finishes, open your Worker’s URL, sign in with your email, and add your first site. Without an email provider configured, the sign-in link is returned on screen (dev mode) so you can get in immediately.
Manual deploy
$ git clone https://github.com/AshikNesin/404less && cd 404less $ npm install && npm --prefix web install $ npx wrangler d1 create 404less # paste database_id into wrangler.jsonc $ npm run deploy # builds the dashboard, applies migrations, deploys
Run it locally first
$ npm run build:web && npm run dev # http://127.0.0.1:8787, local D1, no account needed $ npm test # the suite runs inside workerd against local D1
Sign-in links and email digests go out through Resend, whose free tier covers a personal instance. Slack and Pushover digests work without it.
$ npx wrangler secret put RESEND_API_KEY $ npx wrangler secret put MAIL_FROM # optional, e.g. "404less <no-reply@yourdomain.com>"
RESEND_API_KEY means dev mode: sign-in links are returned by the API
instead of emailed. Fine for a single-user instance behind your own domain; set the key
before inviting anyone else.
Limits & budget
Defaults are chosen so a self-hoster never trips a free-plan ceiling by accident. Each is
a variable in wrangler.jsonc.
| Setting | Default | Why |
|---|---|---|
MAX_SITES_PER_TEAM |
5 | Keeps crawl volume and D1 writes predictable |
EVENT_RETENTION_DAYS |
90 | Nightly prune keeps D1 far under its 500 MB cap |
| Ingest rate limit | 500 hits / site / hour | Protects the 100k daily D1 write budget |
| Crawl pages per run | 100 (max 500) | Per-site setting on the Crawler page; counts the pages a run discovers |
CRAWL_INTERVAL_HOURS |
24 | How often sites with scheduled crawling are crawled |
Cloudflare’s own numbers: 100k Worker requests, 100k D1 writes and 5M reads and 100k Durable Object requests per day on the Free plan, 50 outbound requests per invocation, and five cron triggers per account. 404less crawls without Queues: a cron tick every minute checks up to 40 links and stops, and the next tick carries on, so a crawl never exceeds what one invocation may do. A tick with nothing to do only reads.
Updating
Pull the latest commit and run npm run deploy again. Migrations are additive
and apply automatically; the managed broken-links list is preserved across upgrades.
Custom domains are declared in wrangler.jsonc under routes;
remove or replace the 404less.com entries with yours.