bark-worker: the Bark server that runs as a Cloudflare Worker
Bark Server on Cloudflare Worker
At a glance
- What is it?
- bark-worker reimplements the Bark-Server API on Cloudflare Workers, storing push state in D1 or KV so that iOS Bark users can run their own backend without a server of their own. It is a small, well-scoped project, and its real constraints come from Cloudflare quotas rather than from the Bark protocol.
- Who is it for?
- bark-worker suits an individual or a small group of Bark users who want their own push backend and would rather not keep a machine switched on, and it suits developers who already live inside a Cloudflare account.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 43 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Bark backend that fits inside an existing Cloudflare account
Bark is an iOS app for pushing custom notifications to an iPhone. What Bark needs on the other side is a server that holds device keys and delivers the push payloads, and the reference implementation of that server is a separate project called Bark-Server. bark-worker is a reimplementation of that server shape on Cloudflare Workers. The project's own framing is that it offers privacy-aware users a cheap and private bark backend, and the hosting bill is close to zero for a personal scale of use because a Worker is a serverless function and the state sits in a Cloudflare storage product rather than in a virtual machine. The audience is therefore two groups: iOS users of Bark who want control over where their notification traffic is handled, and developers with a Cloudflare account who would rather ship a Worker than operate a box. There is no homepage listed for the project, which fits an infrastructure component that is used by pointing an app at a URL rather than visited.
The full Bark-Server API surface, with path based parameters
Compatibility is the design constraint that matters here, because the client is a closed iOS app and the server has to answer what it asks. The project lists full support for the Bark-Server APIs, naming them explicitly:
- `register`
- `ping`
- `healthz`
- `info`
- `push`Those five routes cover the practical lifecycle: registering a device key, checking that the endpoint is alive, reporting server info, and delivering a payload. Alongside them the project lists path based parameters resolve, which is a compatibility feature rather than a convenience. A URL driven client expects to be able to place the device key and the message in the request path, and a router that only accepted a JSON body would break that. Health and info routes are worth noting for anyone running this behind a load balancer or a monitoring check, since they give a trivial liveness and version probe without touching storage. The repository backs this up with a test/ directory, a test.sh script, and a test script wired to the Node test runner, so the API contract is exercised rather than assumed.
D1 or KV, and the binding name has to be exactly database
Storage is where the two flavours of this project diverge. Both variants expect the same binding name, which is the one detail that trips people up during setup. The D1 version asks you to create a Worker and a D1 database and bind the D1 database to the Worker with name database. The KV version asks for a Worker and a KV Storage bound to the Worker with name database. Because the binding name is identical, the two versions are largely interchangeable from the configuration point of view, and the code has two entry points, main.js for the D1 build and main_kv.js for the KV build. The project recommends D1 for its higher usage than KV, and carries a caution that after Cloudflare D1 left beta the KV version may eventually be deprecated. That recommendation matters for anyone planning more than a personal device list: a KV namespace has a smaller request allowance than a D1 database, and the project states plainly that the KV version will probably not support MCP because of limited quota.
Batch push overrides the single device key in both API versions
One behaviour is called out with enough emphasis to be considered a contract. The project states that batch push has the highest priority: if device_keys is specified and not empty, device_key is ignored, in both V1 and V2 APIs. That is a precedence rule for the push route, and it is the sort of detail that quietly changes behaviour if you write a client that sends both fields. It also explains why the project lists multi device key to one device and device key alias among its tips, with fuller guidance in doc/tips.md. The tips page is where device key management is documented, and it is worth reading before a group deployment, because a single physical iPhone can be addressed through several keys and an alias mechanism that hides the underlying key value. Separately, the MCP route is mentioned as something that may be optimisable, which suggests the project has an MCP surface of some kind even though the README does not list it among the five supported APIs.
Migrations and deploys are both npm scripts, and deploy runs them first
The operational surface of the repository is small and lives in package.json, where the scripts give you the whole lifecycle:
"scripts": {
"test": "node --test",
"cf-typegen": "wrangler types",
"db:migrate": "wrangler d1 migrations apply database --local",
"db:migrate:remote": "wrangler d1 migrations apply database --remote",
"deploy": "wrangler deploy",
"dev": "wrangler dev",
"predeploy": "npm run db:migrate:remote",
"preview": "wrangler dev"
}Two of those lines change how you should work. The predeploy hook runs the remote migration before every deployment, so schema changes and code changes travel together and a fresh D1 database is brought up to date as part of the deploy rather than as a separate manual step. The local counterpart, db:migrate, applies the same migrations against a local database, which is what you want before pushing anything. The dev and preview scripts both run wrangler dev, one for normal iteration and one for the preview flow. The project also offers a one-click deploy button for Cloudflare Workers, and points to a manual setup path in doc/setup_guide.md. The deployment token needs D1 permission, and a domain is required in countries or regions where worker.dev is unavailable.
Maintenance and licence: a small tree with a clear GPL-3.0 stance
The repository is a single Worker project rather than a monorepo. The top level holds main.js and main_kv.js for the two storage backends, wrangler.jsonc for Worker configuration, a migrations/ directory for D1 schema, doc/ for the setup guide and tips, examples/ with two working samples named lunar_birthday_reminder and reduce_day, plus a test/ directory and test.sh. That the samples are checked in at all is a good sign, because they show the request shape rather than leaving you to guess it. Release tags are being published: v2.2.6 on 2025-12-03, v2.2.5 on 2025-09-20 and v2.1.6 on 2025-04-22, and the last push to the default branch was on 2026-09-12, so the code has moved since the newest tag. Everything in the project is licensed under GPL-3.0, which for a self-hosted backend means that if you modify and redistribute the server you are obliged to keep that licence. Anyone embedding the Worker in a closed product should read the licence text before doing so.
Against a real server on a VPS, the trade is a zero-ops backend against a quota ceiling
The genuine alternative is to run the upstream Bark-Server yourself on a machine you control, and the difference in approach is worth stating plainly. A conventional Bark-Server runs as a long-lived process with a database behind it, which means predictable performance, no per-invocation cold start, and no dependency on a serverless request budget. bark-worker inverts that: there is nothing to keep running, deployment is a single command that also migrates the database, and the operational surface is limited to a Cloudflare account and a binding. What you give up is headroom, because KV quota is explicitly called out as a limit and the D1 path inherits Cloudflare's SQL database constraints. For a personal push server that receives a few dozen notifications a day, that ceiling is irrelevant. For a shared service for a whole faculty, it is the first thing to check, alongside whether pushing from a Worker to Apple's push infrastructure behaves acceptably at that volume.
Editorial conclusion
bark-worker suits an individual or a small group of Bark users who want their own push backend and would rather not keep a machine switched on, and it suits developers who already live inside a Cloudflare account. It is the wrong tool for teams that need an unrestricted request quota, offline delivery guarantees, or a storage engine with predictable SQL semantics, since the KV path is capped by namespace quota and the D1 path is a Cloudflare SQL database rather than a general datastore. Before deploying, create the D1 database or KV namespace and bind it with the exact name database, apply the migrations in migrations/ against that binding, and check whether worker.dev is reachable from your region, since the project notes that a domain is required where worker.dev is unavailable.
Frequently asked questions
What is the difference between the D1 version and the KV version of bark-worker?
The D1 version stores state in a Cloudflare D1 SQL database and the KV version stores it in a KV namespace, and both are bound to the Worker with the name database. The project recommends D1 for its higher usage than KV, and states that the KV version will probably not support MCP because of limited quota.
Which Bark API endpoints does bark-worker support?
The project lists full Bark-Server API support, covering register, ping, healthz, info and push, with path based parameters resolve. The healthz and info routes give you a liveness and version probe without touching storage.
How do I apply the database migrations before deploying bark-worker?
The predeploy script runs npm run db:migrate:remote, which applies wrangler d1 migrations apply database --remote, so a deployment migrates the bound database first. For local work the db:migrate script applies the same migrations to a local database.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cwxiaos-bark-worker)Was this useful?