Never sell the same hour twice
the problem
Two people opening the same 7pm slot at the same time is not a rare edge case on a Thursday evening. It is the normal load. Checking availability and then writing the booking is two steps, and anything can happen between them.
what I did
Availability is never trusted from the client. The reservation is a single server-side transaction with a uniqueness constraint on (pitch, time range); the loser of a race gets a clean 'just taken' state and the calendar refreshes under them rather than a failed payment.
In-app purchases on two stores with different rules
the problem
Apple and Google disagree on receipts, on what a restore means, and on what they will approve. A purchase that succeeds on the device but never reaches the backend is the worst possible bug in a paid product.
what I did
Entitlement is decided on the server from a verified receipt, never from the client's word. The client re-validates on launch and after every restore, so a purchase interrupted mid-flight reconciles itself the next time the app opens.
Calendar and notifications that respect the user
the problem
A booking is useless if the player forgets it. But asking for calendar and notification permission on first launch, before the app has earned anything, gets both denied.
what I did
Permissions are asked at the moment they pay off. The calendar prompt appears right after a successful booking, not before. Reminders are scheduled locally so they still fire if the device is offline.
Deep links that survive an install
the problem
Growth happens when someone shares a match invite in a group chat. If the tap opens a store page and the invite is lost after installing, the whole loop breaks.
what I did
Invite links carry their payload through the install, so a new user lands on the actual match after opening the app for the first time, not on a generic home screen.