Context
Pre-printed badges go stale the moment someone changes their name or job title. Walk-ins need a badge now. Several entrances must agree on who has arrived. And the venue's network, which was fine during setup, collapses when a few thousand phones connect at once. The check-in and badge printing features of Eventify, and the self-service kiosk, were built around those facts rather than around the demo.
The challenge
- The spike. Most attendees arrive in the same half hour. Any design that waits for the server per scan queues to death.
- The network. Assume it will go away at the worst moment and come back without warning.
- Duplicates. Double scans, retries and two entrances must not produce two check-ins.
- Badge design. Fields, QR codes, ticket-type colour bands, sponsor logos, and the same output whether printed in bulk or on demand.
- Printers. Different makes, drivers and paper sizes at every venue.
- Data on the desk. A kiosk machine holds personal data; it must hold only what it needs and forget it afterwards.
What we built
- Badge template designer. In the admin console: fields, QR code, conditional elements by ticket type, sponsor placement and a live preview.
- Server-side rendering. Templates render to PDF on the server for both bulk pre-printing and on-demand printing, so a badge looks identical however it was produced.
- Desktop kiosk app. Lookup by QR, name or email; a locked-down self-service mode and a staff mode; print on demand; check-in; optional walk-in registration.
- Local-first data. The attendee list syncs down before doors open. Lookups, check-ins and print jobs run against local storage; a background sync pushes check-ins up and pulls attendee changes down.
- Idempotent check-in. Each scan carries a client-generated key. The server accepts the same key any number of times and records one check-in.
- Printer abstraction. A driver layer with a named printer per kiosk, status monitoring and a retry queue separate from the check-in queue.
- Reconciliation and clean-up. An after-event report of scans per entrance and per kiosk, and a cache wipe when the kiosk signs out.
Architecture
Key decisions
1. Local-first rather than a thin client
The first version confirmed every scan with the server before showing success. It worked in the office and queued to death at a large conference when everyone arrived at once. The rewrite made the local store the source of truth during the event and the server a destination for reconciliation. The third iteration works with no network at all and catches up on reconnect.
2. Idempotency keys generated on the client
A key is created the moment a scan happens, before any network call. Retries, double taps and two entrances scanning the same badge all carry keys, and the server records one check-in per key. Counting became boring, which is the goal.
3. Two queues, two states
A failed print must not undo a check-in, and a failed sync must not block a print. Print jobs and check-in events live in separate local queues with separate retry rules.
4. Render on the server
Bulk pre-print and on-demand badges come from the same PDF renderer, so a replacement badge at the desk matches the one printed a week earlier. The kiosk only needs to send a PDF to a printer, which keeps the driver layer small.
5. Merge rather than overwrite
When connectivity returns, attendee data from the server wins and check-in events from the kiosk are appended. Neither side overwrites the other's facts.
6. Hold the minimum, then forget
The kiosk caches only the fields needed to find a person and print a badge. Signing out wipes the cache. The rule follows the data-minimisation approach in our privacy work.
Outcome
Registration desks keep moving through the rush and through network outages. Walk-ins get a badge in a single flow. Badges from bulk printing and from the kiosk are indistinguishable. After the event, organisers reconcile scans per entrance from the report rather than from staff memory. Exhibitors benefit too: the badge QR feeds lead retrieval without any extra setup.
What this means for you
Any application used at a counter, in the field or on a shop floor faces the same three problems: bursts, unreliable connectivity and devices that hold personal data. Local-first storage, idempotent writes and separate queues for separate side effects solve them in every domain we have applied them to. If that sounds like your clinic check-in, warehouse scanner or point-of-sale, start with a discovery sprint or read about custom software development.