Omnix
All articles
Product·5 min read

Why we built Omnix offline-first

The internet drops. Power flickers. The till has to keep running. Here's how the desktop app handles it — and why it'll never become a SaaS web app.

JFJustin, founder
D

Two years ago, on a Tuesday, the customer who would become our first paying user lost their Safaricom internet for forty-three minutes during the lunch rush. They had three cashiers ready to ring up sales. The web-based POS they were trialling refused to do anything without the connection.

That's the day we decided to build a desktop app instead of a web app.

Offline-first is not a marketing line for Omnix. It's the architecture. The desktop binary ships SQLite, your full database lives on your machine, every query is a few microseconds away, and a network drop is a non-event for the cashier. When the internet comes back, sync happens in the background.

This costs us things. Our update story is harder — we have to ship a real installer with code-signing and an auto-updater, not just push a deploy. Our cross-device collaboration is harder — we have to run a master/client topology over LAN with conflict resolution, not just rely on a server. Our audit story is harder — we have to be sure no sensitive data leaks through the diagnostic telemetry channel.

But the user experience is on a different planet. Sub-300ms sale completion. Zero loading spinners. Working through a power cut on a UPS for as long as the UPS holds. Working through a Safaricom outage indefinitely. Closing a Z-report at the till with no anxiety about whether the day's data will survive the hand-off.

We won't add a "cloud version" that hosts the database centrally. The trade-off isn't worth it. What we will keep adding is better synchronisation — branch-to-branch, owner's-phone-to-till, encrypted nightly backup to R2. Synchronisation across devices that all hold their own copy of the data is the right pattern for Kenya.

The infrastructure of the country isn't ready for cloud-only software. Maybe it never needs to be.