ZebIQ Technology

// INSIGHTS

Offline-first event systems for when venue WiFi dies

6 min read

The uplink drops at 10:40 on day one. Three hundred delegates are queued at four check-in counters. The badge app spins. This is the ordinary case, not the rare one. Last-mile fibre gets cut by a road crew, a hotel in-house ISP throttles under load, a tented venue in Rajasthan loses power to the rack. We design event software so that none of that reaches the delegate. The app never knew the internet was there.

The failure we design for

Most event apps degrade in a specific order. The WAN goes first. Then the API times out at thirty seconds instead of failing fast. Then the front end shows a spinner with no timeout at all, and a volunteer at counter three starts refreshing the page, which evicts the cache and leaves a blank screen. By then the queue is ninety people deep and someone has fetched a printed list.

We do not treat connectivity as a feature that might be missing. We treat it as an optional accelerator. The delegate-facing build has to complete every core task with the network interface disabled. Check-in, badge lookup, session scanning, agenda, floor maps, speaker bios, sponsor content, feedback capture. All of it runs from the device.

The uncomfortable part is that this constrains what you can build. Live seat availability across six halls cannot be truly offline. Neither can real-time payment authorisation. We tell clients which features are network-dependent before the build starts, and we design a visible degraded state for each one rather than pretending.

Numbers from the field

0 requests
Network calls needed for a full check-in cycle after first load
under 90 seconds
Atomic rollback to the previous hashed release
8-14 MB
Typical precached content package bundled into the build artefact

What offline actually means

Content bundled, not fetched

Agenda, speaker data, maps and images are compiled into the build artefact and precached by the service worker on install. Nothing is pulled from a bucket at runtime, so an object storage outage is invisible.

Immutable hashed releases

Every build ships under a content hash and is never mutated in place. Cache busting is automatic because the filename changes, and the previous hash stays live for instant rollback.

IndexedDB write queue

Scans, check-ins and form submissions are written locally first with an idempotency key, then replayed when a link returns. The UI confirms on local write, not on server acknowledgement.

LAN-origin QR codes

Printed and on-screen codes point at a local hostname resolved by DNS on the venue LAN, not a public domain. No WAN means no dead QR code.

Build rules

  1. Run the three-switch test

    Before sign-off we turn the database off, the storage bucket off and the entire cloud deployment off, then complete a full delegate journey on a cold device. If anything breaks, it is not shipped.

  2. Give every write an idempotency key

    The key is generated on the device at the moment of the action. Replay after the WAN returns is safe because the server de-duplicates on that key, even if a tablet retries the same queue four times.

  3. Decide the conflict rule per entity

    Badge state uses an append-only scan log so nothing is lost. Editable profile fields use last-writer-wins with a device timestamp, which we accept is lossy and say so.

  4. Pin the clock

    Tablets drift, and one device set to the wrong timezone will reorder an entire log. We stamp writes with both device time and a monotonic counter, then reconcile against server time on replay.

What usually goes wrong

Captive portals are the most common killer. A hotel or exhibition centre network intercepts the first HTTPS request and injects a login page. The service worker sees a 200 response that is not your app, caches the portal, and every device on that SSID now boots into a login screen. The fix is a dedicated event SSID with no portal, and a service worker that validates a response signature before caching. If we cannot get a portal-free SSID, we say so in writing during the site survey.

The second failure is HTTPS on the LAN. Service workers require a secure context, so a plain-HTTP local hostname will not register one. You either run a local certificate authority and install the root on every managed device, which is workable for staff tablets and painful for delegate BYOD, or you keep the offline app on the public origin and use LAN-origin codes only for kiosk and staff devices. Both are compromises. Anyone claiming otherwise has not run it on a delegate's four-year-old Android phone.

Third, replay storms. Two hundred devices reconnect at once when the uplink recovers and flood the API with queued writes. We rate-limit replay with jitter and cap concurrent batches, otherwise the recovery itself becomes the outage.

Common questions

If the app works offline, why do we still need bonded uplinks?

Offline-first protects the delegate experience. It does not protect live streaming, payment capture, remote dashboards or the client's own laptops. We bond multiple carrier links with automatic failover so the show floor has a working WAN, and build offline-first so a failover gap of forty seconds is not visible to anyone in a queue.

Can we push an agenda change during the show if there is no internet?

Yes, if the change is served from the venue LAN. We can publish a new hashed release to a local origin and have devices pick it up over WiFi with no WAN involved. If devices are on mobile data and the WAN is down, they stay on the last good release, which is the correct behaviour.

What does this add to the project cost?

Building offline-first from the start typically adds fifteen to twenty-five percent to front-end effort compared with a network-dependent build. Retrofitting it onto a finished app costs considerably more, because the data model and the write path both have to change. It is a decision to make at kickoff, not in week three of a four-week build.