CLI tool
SharzyL/pastebin-worker avatar
SharzyL/pastebin-worker

Pastebin Worker: a Cloudflare-hosted pastebin you deploy with wrangler

Pastebin on Cloudflare worker, with friendly CLI usage and rich features

1,052 stars364 forksTypeScriptMIT

At a glance

What is it?
SharzyL/pastebin-worker puts paste storage on Workers KV and R2 behind a Worker, with a Python CLI, a documented HTTP API and an AI-agent skill file. It is a good fit if your domain already lives on Cloudflare and you accept KV write limits as your real ceiling.
Who is it for?
Adopt it if your DNS is already on Cloudflare, you want a pastebin at a domain you control, and your traffic fits the free tier's 1,000 KV writes per day. Do not adopt it if you need a pastebin that runs outside Cloudflare, or if you cannot live with R2 having no native object expiration.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem it solves, and who it is aimed at

The README states the project's philosophy as "effortless deployment, friendly CLI usage, rich functionality", and the deployment path backs that up: clone, create a KV namespace and an R2 bucket, edit wrangler.toml, run pnpm install, pnpm wrangler login, pnpm build:frontend and pnpm deploy. If your domain is hosted on Cloudflare, that is the entire setup. There is no database to provision, no container to keep patched, and no server to monitor between deploys.

The audience is narrow and specific. It is for someone who already has a Cloudflare account with a domain on it and wants a pastebin at their own hostname rather than on a third-party site. The public instance at shz.al exists as a demonstration, and the homepage in the repository metadata points there, but the README frames self-hosting as the normal case. The secondary audience is people who paste from a terminal often enough to care about a CLI: the pb Python script requires Python 3.9+ with the requests package, switches to multipart upload above 5 MiB, and shows a progress bar.

A third audience appears in the README's usage list. doc/skill.md is described as "a concise, AI-agent-oriented packaging of the API", intended to be handed to a coding agent so it can upload, fetch and manage pastes. That is an unusual artifact to ship in a pastebin repository, and it suggests the maintainer expects programmatic consumers rather than only humans with browsers.

The KV and R2 split, and why it decides your cost curve

The architecture is a Worker in front of two storage services, and the split between them is the most consequential design decision in the project. Small pastes go to Workers KV. Content above a threshold named R2_THRESHOLD goes to R2. The README explains the reason directly: KV honors per-key expiration natively, so expired pastes disappear without any cleanup job, whereas R2 has no built-in expiration. Cleaning up expired objects in R2 would mean periodically listing and scanning every object in the bucket, and the README calls that costly in Class A and Class B operations as the bucket grows.

That is a real trade-off rather than a marketing line. The cost of native expiry in KV is that KV is the tier with the tightest write limits: 1,000 writes per day on the free plan. The benefit is that garbage collection is free. A design that put everything in R2 would have cheaper storage per byte and no per-key expiry, and would need a sweeper. A design that put everything in KV would avoid the threshold logic entirely and hit the write ceiling sooner for large files.

The same split appears in the request path. The README notes that a single request body is capped at 100 MB by Cloudflare, which returns HTTP 413 before the Worker runs. Larger uploads have to go through the website or the pb CLI, both of which the README says chunk the upload transparently. So the 100 MB figure is a platform boundary, not a project setting, and you cannot raise it from wrangler.toml.

Beyond storage, the README lists features that live in the Worker: syntax highlighting via highlight.js, client-side encryption, markdown files rendered to HTML, a URL shortener, and what it describes as "smart and tweakable handling for Content-Type and Content-Disposition". The last one matters more than it reads. Serving a paste with the wrong content type turns a text file into a download or, worse, into something the browser renders. The README does not document the exact rules, so if you care about that behaviour you will have to read the Worker source rather than the README.

Deploying it: the commands and the keys that matter

The deployment sequence in the README assumes node and pnpm are installed. First you create the two backing resources, substituting your own bucket name:

pnpm wrangler kv namespace create PB pnpm wrangler r2 bucket create <name>

Then you edit wrangler.toml, filling in the KV namespace ID and the R2 bucket name. The README says the file's comments explain the rest, which is where you will find R2_THRESHOLD and the optional Workers Logs setting. After that:

pnpm install pnpm wrangler login pnpm build:frontend pnpm deploy

The build step is not optional and the order matters. The frontend and the Worker are built separately, and the README is explicit that build:frontend:dev points the API endpoint at your deployment URL while build:frontend points it at http://localhost:8787. Getting those two backwards produces a deployed frontend that talks to a local worker that is not running, which is a confusing failure to debug after the fact.

Administration is thin but present. Deleting a paste is pnpm delete-paste <name-of-paste>. Listing pastes is pnpm -s wrangler kv key list --binding PB > kv_list.json, which dumps the KV keys to a file you then inspect yourself. Note that this lists KV keys, so it will not enumerate objects sitting in R2 above the threshold.

For a private deployment, the README shows adding a [vars.BASIC_AUTH] table to wrangler.toml with username keys mapped to bcrypt hashes, generated by running ./scripts/bcrypt.js. The README's example shows two users and states that every POST request and every access to static pages then requires HTTP basic auth, while reads of existing pastes stay open. Without that table, the README does not describe any other upload restriction, so a public deployment is open to anyone who finds it.

Where it stops being the right tool

The free tier's binding limit is 1,000 KV writes per day, which the README equates to 1,000 uploads per day. That is a personal or small-team ceiling, not a community one. If your pastebin is going to be hit by a class of students, a CI system posting logs, or anything that writes in bursts, you are on the $5/month paid plan or you are dropping writes. Reads are the looser constraint at roughly 100,000 fetches per day on the free tier, so a read-heavy deployment with few authors is the shape this project handles best.

The R2 threshold is the second sharp edge. Because R2 has no native expiration, anything above R2_THRESHOLD persists until something deletes it. The README does not describe a garbage collection job for R2 objects, and it explains why writing one is awkward. If your use case is large files that are supposed to expire, this is the wrong storage design for you, and no configuration value fixes it.

The third limitation is the platform lock. The project targets Cloudflare Workers, Workers KV and R2 specifically, and the README's deployment instructions assume your domain is hosted on Cloudflare. There is no documented path to run it on another provider or on a plain VPS. If you want a pastebin you can move between hosts, this is not that.

Finally, the authentication model is coarse. BASIC_AUTH is a single global gate: it protects posting and static pages, and it does not give per-user paste ownership or per-paste access control in what the README describes. The admin URL returned on upload, of the form https://example-pb.com/YCDX:Sij23HwbMjeZwKznY3K5trG8, is the per-paste secret, so anyone holding that URL can act on the paste. Treat the admin URL as a credential.

What you would use instead, and how it differs

The obvious alternative for a self-hosted pastebin is a conventional server application backed by a database, run on a VPS or a container host. The difference is not cosmetic. A database-backed pastebin stores paste metadata and content in one place, which means expiry is a query or a scheduled job under your control, per-user accounts are natural, and you can enumerate and migrate everything with standard tooling. It also means you own the server: patching, TLS certificates, backups, and a process that has to stay up. Pastebin Worker trades that operational surface for two managed services with their own limits and their own pricing pages.

A second comparison is worth making inside the same platform. If your pastes are small and short-lived, storing everything in KV and skipping R2 entirely removes the threshold logic and the orphaned-object problem, at the cost of KV's storage pricing and its write ceiling. Conversely, if your pastes are large and long-lived, going all-in on R2 removes the split but leaves you writing the sweeper the README warns about. The project's choice to split is a reasonable middle, and it is a choice you inherit rather than one you configure away.

For the terminal workflow specifically, the alternative to the pb script is calling the HTTP API directly with curl, which the README explicitly supports and points at doc/api.md. The pb script adds multipart upload above 5 MiB and a progress bar, so the difference is convenience for large uploads rather than capability. If you are scripting in a language other than Python, doc/api.md is the artifact you want, and doc/skill.md is the same surface packaged for a coding agent.

Maintenance, upgrade surface and licence

The maintenance burden is mostly version drift in three places: the Worker runtime, wrangler, and the frontend build. Because the frontend is built separately from the Worker and the two are wired together by which build command you run, a frontend rebuild that changes the API endpoint assumption is the kind of change that passes local development and fails after deploy. The README's development section is the reference here: pnpm dev:frontend for the Vite server, pnpm build:frontend:dev plus pnpm dev for the Worker, and pnpm test, pnpm coverage, pnpm fmt, pnpm lint and pnpm typecheck before committing.

There are no releases listed for the repository, so upgrades are a matter of pulling the default branch, which is goshujin, and rebuilding. That means you should read the diff before deploying, particularly around wrangler.toml, since that file holds your KV namespace ID, your R2 bucket name, R2_THRESHOLD and any [vars.BASIC_AUTH] entries. A merge that touches that file is a merge that can break your deployment or silently drop your auth gate.

The licence is MIT, which permits commercial and private use and modification, and requires that the copyright notice and permission notice be preserved. That is the whole of what the repository metadata states; it is not legal advice, and if you are deploying this as part of a commercial service you should read the LICENSE file in the repository rather than this summary.

One cost line to keep in mind while planning: Workers Logs is off unless you enable it in wrangler.toml, and the README lists it as optional. If you turn it on for debugging and leave it on, verbose logging becomes a billed line item at 20 million events per month included on the paid plan, with 7-day retention instead of the free tier's 3 days.

Editorial conclusion

Adopt it if your DNS is already on Cloudflare, you want a pastebin at a domain you control, and your traffic fits the free tier's 1,000 KV writes per day. Do not adopt it if you need a pastebin that runs outside Cloudflare, or if you cannot live with R2 having no native object expiration. Before you commit, verify three things against your own account: the KV namespace ID and R2 bucket name you paste into wrangler.toml, whether R2_THRESHOLD matches the paste sizes you actually expect, and whether you want BASIC_AUTH enabled at all, since without it anyone can POST to your deployment.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. SharzyL/pastebin-worker on GitHub
Community notes

Community notes