Get in touch
Product

Ticketing, rebuilt

Six screens became three. The interesting part is not what we removed, but what we had to move to the server to be allowed to remove it.

By Ovadev4 min read

All posts
  • ticketova
  • checkout
  • product

The old flow had six screens between wanting a ticket and having one. None of them were badly built. Every one of them existed because somewhere, at some point, a question had no default.

taps to buy
3

was six screens, eleven taps

median confirm
820ms

p95 at 1.4s

completion
+18%

same traffic, four weeks after

Every screen was a question with a default#

We listed the six screens and next to each one wrote the answer that 90% of buyers gave. Five of the six had one. A screen that asks a question with a 90% answer is not a choice, it is a confirmation — and confirmations belong on the receipt, not in the flow.

ScreenQuestionWhat 90% answered
Seat classWhich tier?The one they tapped from
QuantityHow many?The number in the previous step
DeliveryPost or wallet?Wallet
FeesAccept the fee?Yes — it was never optional
AccountSign in or guest?Guest, then an account after
Five questions, five defaults, five screens that could become one line on the confirmation.

What had to move to the server#

Removing a screen usually means the server now has to be right about something. Three cases carried most of it:

  1. 01
    The hold happens on tap

    The old flow held a seat when you reached the payment screen. Now it holds on the first tap, for ninety seconds, and releases on abandon. Buyers stopped losing seats between screens, which was the single biggest complaint.

  2. 02
    Fees are resolved once

    Fee logic used to run in two places and occasionally disagree by a rappen. It now resolves server-side with the hold and travels with it — the client never computes money.

  3. 03
    The account is created after

    We create the account from the payment record once the purchase clears, and email a link to set a password. Nobody has ever been happy to make an account before being allowed to buy something.

Sub-second, and how it is measured#

“Sub-second confirm” means from the tap on Pay to the ticket being on screen and valid at the door — not to a spinner, not to a redirect. The number that mattered was the p95, because the median was already fine and the tail is what people remember.

sql
-- the hold is a row with a deadline; expiry is a query, not a job
select seat_id
from seat_hold
where event_id = $1
  and expires_at > now()
for update skip locked;
No cron sweeping expired holds — an expired hold simply stops matching.

skip locked is doing the quiet work there: two buyers reaching for the same seat at the same moment no longer queue behind each other, the second one just gets the next free seat in the same round trip.

What we would do differently#

Would you cut the seat-class screen again?

Yes, but later. It was the one removal that needed a fallback: for multi-tier venues we now show tiers inline on the map instead of as a step, which took another two weeks we had not planned for.

Did guest checkout hurt repeat purchases?

No — repeat rate went up. People who buy twice make an account voluntarily, and the ones who never come back were never going to maintain a password either.

Ninety seconds for a hold — why not five minutes?

Five minutes is generous to the buyer and brutal to the venue on a hot event. Ninety seconds covers a card payment with a 3-D Secure detour, and we extend it once automatically if the payment sheet is open.

Ovadev

A software company in Baar, Zug. We build our own products, run them afterwards, and write down what that teaches us.

Get in touch
Read next

More from the studio — product first, then the rest of the feed.

All posts
© 2026 Ovadev GmbHMade in Switzerland