Astro

Offline-first

GraphQL

Performance

Festival App

Building a Reliable Festival App: The Story Behind Our Sync System

How we built an offline-first synchronization system for a festival app to ensure reliability under unstable network conditions.

Nichola Bauwelinck
Nichola Bauwelinck March 26, 2026

At a busy festival like Billie’s Craft Beer Fest, the last thing you want is an app that doesn’t function well because of bad internet. With thousands of people in one place, slow or unstable connections are inevitable, and that’s exactly what we had to design for. Our goal was simple: make sure the app always works, even when the network doesn’t. To make this happen, we built a smart offline-first synchronization system which we called syncMaster3000.

The problem with online first apps

Online first apps are designed with the idea that there will always be an internet connection. In normal situations, this is no problem. However at a crowded festival this can cause problems fast. Every action in the app like loading beers, opening the map or checking brewery details needs a request to the server. When there are network issues these requests can take much longer or fail completely.

Looking into offline caching

To solve this problem, we started looking into offline caching libraries that would work well with the GraphQL API of Vendure. We wanted something reliable, expandable and easy to integrate into our existing setup. During our search, we quickly find Apollo, a popular library that provides powerful tools for caching and managing GraphQL data on the client side.

However, we quickly realized that Apollo didn’t fully match our needs. Even though it comes with caching out of the box, it is still largely built around an online-first approach and didn’t give us the level of control we needed for a true offline-first experience in a festival environment. We needed something that could handle custom synchronization logic, work reliably with unstable connections, and give us full control over what data gets synced and when.

That’s why we decided to build our own solution: syncMaster3000, a custom synchronization system tailored specifically to our use case.

The idea: only download the changes

Instead of constantly fetching all data from the server, we took a more efficient approach. We built one central sync request that asks the server:

“What has changed since the last time I checked?”

The server then responds with only the relevant updates, such as new beers, updated breweries, or deleted entities. By only syncing the changes, the app uses much less data and stays fast, even on weak or unstable connections.

How syncMaster3000 works in practice

When the app starts, it first loads data from local storage. This way the user can instantly see something on their screen without waiting. In the background, syncMaster3000 sends a request with the last known sync timestamp. Once new data is received, the local cache is updated and the UI refreshes automatically.

This means users always have access to data, even if they are temporarily offline, while still getting updates whenever a connection is available.

Handling unreliable connections

Because we designed the system for unstable environments, syncMaster3000 is built to handle failures gracefully. If a sync request fails due to a bad connection, the app simply retries later without interrupting the user.

Even if the user is offline for a longer period, the app remains fully usable thanks to the locally stored data. Deleted or updated data is correctly handled during the next successful sync, ensuring everything stays consistent.

Performance and user experience

By only syncing changes instead of full datasets, we significantly reduce the amount of data that needs to be transferred. This results in faster load times and less strain on both the network and the server, especially during peak festival hours.

For users, this means the app feels fast and reliable. They can browse beers, explore breweries, and use the map without worrying about loading times or connection issues.

Conclusion

Building for unreliable networks forced us to rethink how apps should work. Instead of relying on constant connectivity, we designed for independence. With syncMaster3000, we turned a potential weakness into a strength and created an app experience that users can rely on, no matter the connection.