Local-Second, Event-Driven Webapps

Wed, 17 Sep 2025 09:26:00 +0000
Event Sourcing, Architecture, Rust, Web Applications, React, Local-First, ElectricSQL, Offline, PostgreSQL

You're on your way to a family vacation in Italy, driving from Poland, and it's a long drive of over 1500 km, so you decide to make a stopover in Austria. After an entire day behind the wheel, you arrive at the hotel, eager to stretch your legs, give the kids an occasion to run around, and explore what the Austrian city has to offer.

You enter the hotel, happy that the driving for today is over, and walk over to the front desk. But here the problems start! The Internet connection is down, and they can't check you in. "But," you say, "I've got everything in here, the booking, the confirmation, can't you just give me a key to my room and complete the check-in later?". "No," they reply, "checking in through the System is the only way to get a key". The System is, of course, an ordinary in-browser web app.

They ask you to wait. You do so; 10 minutes pass, 20 minutes—the kids are starting to ruin the lobby—finally, 30 minutes later, the connection is back online, and you check in successfully. On one hand, you might say, it's only 30 minutes. On the other hand, you've started programming at around age 12, and you can't help but wonder—are we doomed to live with such technology? Or can we do better?

Of course we can! It's just poor (but probably cheap) system design that provides "sub-optimal"—to put it mildly—user experience in case of network problems.

Local-first?

I've been a fan of the local-first approach for a long time. It's full of good ideas which feel "right": you own your data; a central server is a convenience, not a necessity; the application is resilient to disruptions. Hence, I thought—maybe that's the solution to the hotel check-in problem?

When driving the next day with plenty of time to think, a full-blown local-first app for this type of problem would probably be too much. The tools and techniques are available, such as CRDTs and automerge, but they excel in areas like collaborative editing and mobile apps with intermittent connectivity.

But we can take some of the ideas and apply them to create a "local-second" solution. By default, the system would operate in a traditional, centralized client-server fashion. That is, a completely standard webapp+HTTP API.

However, when there are network problems, we would degrade into an offline mode, which offers limited functionality. The crucial services are still available—and data is being buffered until the connection is restored.

In our case, such crucial functionality is checking guests in, so that they can rest after a long trip; other operations might be unavailable.

The event-driven PoC

Armed with AI coding assistants (Claude Code, if you're curious), I've created a PoC application, which implements a skeleton of such a local-second webapp and backend. But before diving into the code, there are a couple of choices to be made regarding the technologies used and the architecture itself.

Unlike in a traditional web app,...