From the outside, an event platform looks like one website. Inside, eventOS is several applications that share one set of rules. I did not start there. I got there by noticing that different kinds of work kept pulling in different directions.
Four kinds of work that do not want the same home
The organiser tools are long-lived screens with a lot of state. An organiser sets up an event, edits ticket tiers, checks sales and comes back the next day.
The part that decides things (is this ticket sold, is this payment complete, may this person be admitted) has to be the only place those answers come from.
Producing a ticket as a document is slow, bursty work compared with answering a web request.
Scanning at the door happens on a phone, inside a venue, often with a poor connection.
Put all four in one deployment and each inherits the others' constraints. Document rendering competes with checkout for the same resources. A change to an organiser screen has to be released together with the code that decides payments. The door app's offline needs leak into a web codebase that will never be offline.
What I separated, and what I refused to separate
I split the work by how it runs. The web experience, the service that owns decisions, the document renderer and the door app are separate applications that can be released and scaled on their own.
I did not split the rules. There is one definition of an event, a ticket, a transaction and an admission, written once and used by every application. If the door app and the organiser dashboard each had their own idea of what "admitted" means, they would eventually disagree, and the disagreement would show up at a venue.
So the applications share definitions, but they do not share authority. Only one of them is allowed to change the state of a ticket or a payment. The others ask.
The cost I accepted
Several applications are more work to run than one. There are more things to deploy, more places a version can drift, and a contract between them that has to be kept honest. I pay for that with shared definitions that every application is built against, so a change to the meaning of a ticket fails the build everywhere at once instead of failing at a venue later.
Two tests I keep applying
If two applications always have to be released together, the boundary between them is decoration. If a rule has to be written twice, the shared definitions have failed. I use those two questions whenever I am tempted to add another service or merge two of them.
The implementation details stay private because this is a live commercial platform. The reasoning is the reusable part: separate by how the work runs, never by who owns the truth.