Marketplace · Track-Day Booking Case study
BookRevs
A European motorcycle track-day marketplace where riders discover and book events, organizers manage capacity and are paid, and the platform mediates the money between them.
Marketplace · Track-Day Booking
BookRevs BookRevs
Senior Full-Stack Engineer · Marketplace Engineering
System map · Platform topology
Production scope
- Two parties, one ledger Bookings, payments and refunds stay reconcilable
- Cannot be oversold Physical capacity, held by waitlist offers
Marketplace platform
Who acts
Rider
Organizer
Administrator
Shared platform
Discovery, track-day catalogue and booking workflows
Platform services
Capacity
Waitlist offers
Payments
Connected accounts
Cancellation
Reviewed requests
Payment ledger
Movements recorded, never inferred from booking status
Production operations
- Idempotent payment webhooks
- Transactional email
- Five-language routing
- Structured logging

Engineering
Next.js · TypeScript · PostgreSQL · Prisma · Stripe
Public product · Proprietary source code
- Role
- Senior Full-Stack Engineer · Marketplace Engineering
- Disclosure
- Public product · Proprietary source code
- Links
- Product website
The problem
What the system had to solve.
A track-day marketplace moves money between two parties who do not know each other. A rider pays the platform, an organizer is paid by the platform, and the platform has to be able to explain every movement afterwards — during a refund, a cancellation or a dispute.
Capacity is physical and cannot be oversold, payment state is decided by an external provider that retries and duplicates its notifications, and the market spans several countries and languages.
What I owned
The responsibility behind the work.
Delivered customer-facing booking workflows, the payment and webhook integration, organizer and administrative functionality, and the production reliability of the transaction paths.
Built booking and discovery journeys, the marketplace payment integration with connected organizer accounts, the payment ledger and webhook handling, capacity and waitlist behaviour, cancellation and support workflows, and the administrative surface behind them.
Engineering approach
How it was built.
Payments run through connected organizer accounts with a dedicated ledger recording movements rather than inferring them from booking status. Incoming payment webhooks are verified and recorded before being applied, so redelivery cannot double-confirm a booking. Full events place riders on a waitlist and freed places become time-bounded offers rather than automatic charges, and cancellations are modelled as reviewable requests with a financial record.
Booking path
- Discover
- Book
- Pay
- Confirm
- Attend
A three-sided marketplace
Three audiences with opposing interests.
A rider wants to find and book a track day, and to get their money back if it is cancelled. An organizer wants to fill an event, control capacity and be paid. The platform has to hold both positions at once, take its cut, and stay correct when they conflict — because a booking is a financial commitment on both sides.
That is what separates a marketplace from a booking form. Money moves between two parties who do not trust each other, mediated by a platform that has to be able to explain every movement afterwards.
Who acts
Riders
- Discover and filter events
- Book and pay
- Join waitlists
- Request cancellation
Organizers
- Create and schedule events
- Set capacity and add-ons
- Manage bookings
- Receive payouts
Administrators
- Oversee the platform
- Invite organizers
- Handle support tickets
- Resolve disputes
Moving money between strangers
Why marketplace payments are their own architecture.
A rider pays the platform; an organizer is paid by the platform. Those are not the same transaction, and treating them as one is how marketplaces end up unable to explain their own balances. Payments run through Stripe with connected accounts for organizers and payment intents for riders, so the money has an owner at every point.
Payment path
- Rider books Payment intent created
- Payment confirmed
- Booking becomes firm
- Platform records the movement
- Organizer paid through their connected account
A dedicated payment ledger records movements rather than inferring them from booking status. A booking tells you what someone asked for; a ledger tells you what actually happened to the money, which is the only thing that helps during a dispute.
Webhooks are not requests
Taking payment events from an external system safely.
Payment state is decided by the payment provider, not by the application, and it arrives as webhooks. Webhooks retry, arrive out of order, and can be delivered more than once for the same event. A handler that assumes otherwise will double-confirm a booking or double-count a payment.
Received events are recorded, so a redelivered webhook is recognised as one already processed rather than applied a second time.
Webhook handling
- Webhook received
- Signature verified
- Already processed? Stop
- Record the event
- Apply the state change
Superseded payment intents are retained rather than deleted. When a payment is retried or replaced, the abandoned attempt is still part of the story of that booking.
Capacity, waitlists and offers
What happens when an event is full.
A track day has hard physical capacity — a finite number of riders can be on a circuit safely. Selling one place twice is not a bug that can be smoothed over afterwards. When capacity is reached, riders join a waitlist rather than being turned away.
When a place frees up
- A place becomes available
- Next waitlist entry identified
- Offer made Time-bounded
- Claimed → booking
- Offer expires
- Place returns to the pool
Events carry schedules, images, links and optional add-ons that riders select alongside the booking itself, so an add-on is priced and recorded as part of the same commercial transaction rather than bolted on beside it.
Cancellations
The path that has to work when everything else went wrong.
Track days are cancelled — weather, circuit availability, an organizer withdrawing. Cancellation is where a marketplace either keeps its riders or loses them, and it is a request with a decision and a financial consequence rather than a button that deletes a row.
Cancellation path
- Cancellation requested
- Reviewed against event and policy
- Decision recorded
- Refund movement recorded in the ledger
- Both parties notified
Support tickets are part of the same system rather than an external inbox, so a dispute about a booking sits next to the booking it concerns.
Getting in, and getting invited
Two different onboarding problems.
Riders self-register and verify with a one-time code. Organizers cannot: an organizer can take other people’s money, so they arrive by invitation with a single-use token rather than by signing up. The two paths are deliberately different because the trust required is different.
Two ways onto the platform
Riders
- Self-registration
- One-time code verification
- Session-based authentication
Organizers
- Invitation only
- Single-use invite token
- Connected payment account required
Built for more than one market
Internationalisation as a structural choice.
European track days are not a single-language market. The application is internationalised across five languages from the routing layer down, rather than having translation retrofitted, which is the difference between adding a market and rebuilding for one.
Supported languages
- English
- German
- Spanish
- French
- Italian
Also structural
- GDPR cookie consent with granular preferences
- Transactional email templates
- Generated booking documents
- Structured logging
Engineering scope
What I worked on.
- Rider booking and discovery journeys
- Marketplace payments with connected organizer accounts
- Payment ledger and idempotent webhook handling
- Capacity, waitlists and time-bounded offers
- Cancellation, refund and support workflows
- Organizer invitation and administrative functionality
- Internationalisation across five languages
Why these decisions mattered
The trade-offs behind the marketplace.
A payment ledger, not derived state
Webhook events recorded before applied
Waitlist offers, not automatic booking
Organizers by invitation
Cancellation as a modelled request
Internationalised from the routing layer
Impact
What the design holds together.
Bookings, payments, refunds and cancellations stay reconcilable across two parties and an external payment provider, with capacity that cannot be oversold and payment notifications that are safe to receive twice.
Technology
The technical surface.
Application
- Next.js
- TypeScript
- React Query
Data
- PostgreSQL
- Prisma
Payments
- Connected accounts
- Payment intents
- Webhooks
Interface
- Tailwind CSS
- Radix primitives
- Schema validation
Reach
- Internationalised routing
- Five languages
- GDPR consent
Operations
- Transactional email
- Structured logging