I’ve been building Solid Objects, a gem that brings Cloudflare’s Durable Objects programming model (addressable objects, durable state, serialized turns) to ordinary Rails applications. Just like Solid Queue, it runs on the MySQL, PostgreSQL, or SQLite database the app already has. No Redis, no Cloudflare account, no separate actor service.
class Counter < SolidObjects::Actor
attribute :value, default: 0
def increment(amount: 1)
self.value += amount
end
end
counter = Counter.ref("global")
counter.increment(amount: 5) # committed result, no worker fleet required
counter.async(:increment, amount: 5) # durable enqueue, a worker runs it later
Counter / global is a logical identity, addressable from anywhere without first creating or locating a Ruby object. Solid Objects activates it when work arrives, commits its ordered turns one at a time, and deactivates it when idle. Synchronous calls need no worker fleet: the caller helps execute the actor through the same mailbox, lease, and fencing path a worker would use.
This is an early release and I’d love feedback. The feedback I’m most curious about right now: is the workerless synchronous path the right default for Rails apps? or would requiring a worker be less surprising?
Here are some docs if your curious: https://solidobjects.dev/
Thank you!