· via Hacker News – Front Page (native)
Solid Objects ports Cloudflare's Durable Objects model to Postgres, SQLite and MySQL
Solid Objects is an open-source library that implements the Durable Objects actor model on the SQLite, PostgreSQL or MySQL database you already run, with no daemon, broker or vendor account.

What it is
A new open-source library called Solid Objects brings Cloudflare's Durable Objects programming model — long-lived, single-threaded actors with durable state — to ordinary relational databases. According to the launch post on the project's site, which reached the Hacker News front page, each object has an identity, persistent state, and an ordered mailbox, and all of it lives in the SQLite, PostgreSQL, or MySQL database an application already runs. There is no separate daemon to deploy, no message broker, and no platform account. The library ships as an npm package for Node 24+ and as a gem for Rails 7.1+, and it installs its tables into the existing database much like Rails' Solid Queue and Solid Cache.
The model, without the vendor
The post argues that the Durable Objects pattern — one identity handling one call at a time, with state that outlives the request — has until now come bundled with trade-offs. On Cloudflare, adopting it means tying state and billing to a single vendor. The post claims metered pricing is hard to predict, citing a case in which a runaway alarm loop allegedly billed a pre-launch developer $34,000 over eight days despite having no users. Self-hosted alternatives such as celld trade the vendor for a process on every node plus a bucket to replicate into, and add yet another stateful system to back up and monitor. Solid Objects instead treats the application database as the source of truth.
How a turn works
Every call enters an ordered mailbox keyed to the object's identity. A fenced lease decides which process runs the turn, and state changes, scheduled reminders, outbound effects (written to an outbox), and broadcasts all commit in a single database transaction. A worker that has lost its lease cannot commit. Redis is optional and only shortens wake-up latency; PostgreSQL notification channels serve a similar purpose for cross-process wake-ups.
What it replaces
The author describes the homegrown stack this pattern replaces: a row lock, then a Redis lock once the lock must span two requests, an expiry column, a delayed job, a sweeper cron to recover what dies with the process, retry code, and broadcasts that can disagree with the writes they follow — six coordinated pieces collapsed into one object. The post recounts an app whose five-minute cron swept every active account: 2,014 runs in a week and 37 minutes of queue time turned up eight accounts. The author also notes that Shopify separately published essentially the same architecture — inventory reservations moved from Redis into MySQL, one row per unit, claimed with SKIP LOCKED — which the post reads as evidence the problem is current rather than a rediscovery.
Benchmarks and caveats
On a developer laptop with SQLite, a durable call from enqueue to committed completion measured about 2.6 ms at the median within one process. Across two processes relying on polling alone, the wait stretched to roughly a second, which is why PostgreSQL notifications and the optional Redis wake-up exist. The project publishes its benchmark harness and caveats, and cautions that laptop measurements do not predict application capacity.
The limitations are stated plainly: no edge placement or routing between regions, no transaction spanning two identities, and ordered, at-least-once delivery rather than exactly-once — so external effects must be idempotent. The project is pre-1.0, runs in production in a single application with more than 100,000 users, and has no third-party production use yet. A public demo exists at shuffleupandplay.com. For logic that fits entirely inside one request, the post advises, a plain transaction is still the right tool. Next on the roadmap: reproducible benchmarks, more soak time on PostgreSQL and MySQL, then a 1.0 release.
Why it matters
Durable Objects demonstrated that a single serialized actor with its own state is a productive way to solve coordination problems — reservations, countdowns, ticket counters — but adopting it has meant buying into one vendor's runtime and metered billing. Solid Objects makes the model portable: any team already running Postgres or MySQL can get ordered, transactional actors as a library, and the state lives in tables they can query, back up, and migrate themselves. The parallel move at Shopify suggests demand for the pattern extends well beyond Cloudflare's platform. The caveats are real — at-least-once delivery, no multi-object transactions, and a young codebase — but for teams weighing lock-in, the calculus changes: the part that made Durable Objects worth adopting no longer has to be rewritten on the way out.
- #open-source
- #postgres
- #durable-objects
- #cloudflare
- #node-js
- #ruby-on-rails