Realtime by default, not as an afterthought
How Lunora turns every query into a live subscription, with optimistic updates and an offline queue baked in.

Most backends bolt real-time on after the fact. You stand up a separate WebSocket server, add a pub/sub bus, and write a pile of glue to keep clients in sync with the database. It works, but now you've got a second system to reason about, and it drifts out of sync with your actual data more often than anyone likes to admit.
Lunora doesn't do that. Every query is a subscription.
One mental model
You read data with useQuery. That read is the subscription. Any mutation that touches the same
tables re-runs the affected queries and pushes the fresh result to every client watching them. No
channels to wire up, no cache to invalidate by hand.
const messages = useQuery(api.messages.list, { roomId });
const send = useMutation(api.messages.send);That's the whole surface area. Reactivity isn't a feature you opt into here. It's just how reads work.
Optimistic, and fine offline
Mutations apply on the client right away and reconcile when the server confirms. Lose the network mid-write and the change gets queued durably and retried, keyed by a client id so a flaky connection never double-sends.
How it actually works
Each shard is a SQLite database living inside a Durable Object at the edge, with optimistic concurrency control and hibernated WebSocket subscriptions. An idle connection costs you almost nothing, which is what makes live updates cheap and consistent without a central server fanning everything out.
There's a lot more under the hood. I'll go deeper on the internals in future posts, so follow along.
