A hotel group doesn't run one journey with a property if/else branch. It clones the journey per hotel, each with its own trigger and its own duplicate rules.

Ask most workflow builders how to run the same guest journey across a dozen properties, and the answer is a single journey with a property picker bolted onto the trigger, an if/else branch buried three nodes deep that reads "if hotel_id equals X, do this, else do that." It looks efficient on the canvas: one journey, one place to edit, one source of truth. It is also the first thing that breaks the moment two properties need genuinely different timing, different copy, or a service that only one of them offers.
A real multi-property journey builder for a hotel group doesn't collapse everything into one branching monster. It clones. The same logical journey exists once per property, each one wired to its own trigger, each one editable on its own without touching the other eleven.
Take a straightforward post-arrival sequence: send general information after check-in, follow up with the services on offer, then check in on satisfaction later. Three steps, one obvious shape. A group running a dozen properties does not build this as one journey with a hidden property switch inside the first node. It builds the same three-step shape a dozen times, once per hotel, each with its own guest-checked-in trigger.
That sounds like more maintenance until you actually run it. A property adding a spa wants the "services offered" step to mention it. A property closing for a shoulder-season renovation wants the whole sequence paused. Neither change should risk touching a sibling property's flow, and in the cloned model neither does, because there is no shared node for them to collide on. The if/else version cannot make that guarantee: a bug in the shared branch is a bug in every property's flow at once.
The same structural choice shows up in far simpler journeys too. A booking-confirmation flow, just a booking-created trigger filtered down to confirmed bookings, follows the identical one-journey-per-property pattern rather than one journey filtering on both "confirmed" and "which hotel." Simple journeys and complex ones get the same treatment, because the reason for cloning is not complexity. It is isolation.
Cloning by property solves the wrong-copy-to-the-wrong-hotel problem. It does not solve a subtler one: what counts as the same trigger firing twice. A guest checks in, then something upstream resends the same event an hour later, a webhook retried, a nightly resync overlapping a live update. Does that guest get the welcome sequence twice?
Every entity-capable trigger, booking or guest, carries its own dedup configuration to answer that: a dedup window measured in hours, a dedup mode, and a dedup entity key. Two modes exist, and they mean genuinely different things. Window mode treats any duplicate trigger inside the window as one event, full stop, regardless of which specific booking or guest actually caused it. Per-entity mode is narrower: it allows one enrollment per distinct booking or guest id inside that same window, so two different bookings for the same guest can both still enroll separately.
That distinction matters because the two failure modes point in opposite directions. Window mode set on a trigger that should have been per-entity silently drops a guest's second, legitimate enrollment. Per-entity mode set on a trigger that should have been window-deduped lets a genuine duplicate event double-send a welcome message. The setting is not cosmetic. It decides whether a guest with two overlapping stays gets two confirmation flows or one, and whether a noisy sync integration spams a guest or gets absorbed quietly.
Because the setting lives on the trigger, not on the journey template, two properties running the visually identical journey can configure it in completely different ways. A welcome sequence triggered on check-in is the kind of thing most properties want deduped by window: one checked-in event, however many times an integration re-fires it, should produce exactly one welcome flow for that stay. A journey reacting to bookings, where the same guest legitimately books two separate stays inside the dedup window, is the kind of thing that wants per-entity: each booking is its own event and deserves its own enrollment, not a collapse into "this guest already triggered something recently."
This is the part a shared if/else journey cannot express at all. A single journey has a single trigger, and a single trigger has a single dedup configuration. Split into one journey per property, each property's trigger carries its own answer to what counts as a duplicate here, and neither has to compromise to match the other.
None of this matters if cloning a journey across a dozen properties means a dozen times the execution load, and the load does not get handled. At current worker configuration, twenty workers running per cron cycle, the platform processes 1,200 journey executions an hour, which works out to a ceiling of 28,800 a day. That is not a rounded-up marketing figure. It is the actual throughput this pattern has to fit inside.
Two mechanics keep that ceiling from becoming a scramble as automation fans out across multiple properties at once. Executions are claimed through an atomic mechanism that guarantees two workers can never grab the same one, so cloning a journey across a dozen properties does not risk two workers processing the same guest's step twice. And claims are distributed round-robin across tenants, so one hotel group running an unusually active batch of journeys cannot starve every other tenant's sends behind it in the queue. A journey builder for a hotel group only stays honest at scale if a busy week for one group does not degrade a quiet week for another, and that is enforced at the queue, not left to load-balance itself.
Workers crash mid-execution sometimes. That is true of any queue-based system, not a defect specific to this one. What matters is what happens next. A health check runs every five minutes and automatically resets any execution that has been sitting in progress for more than 30 minutes. Without that, a crashed worker would leave a guest permanently stuck mid-journey, never re-picked-up. It just stopped.
That is a small mechanic next to dedup modes and throughput ceilings, but it is the one that turns cloned-per-property from a clean idea into something that survives a bad deploy at two in the morning without anyone noticing a guest fell out of a sequence.
The one-journey-per-property pattern is not a philosophy about tidiness. It is what falls out of taking two things seriously at once: that a dozen properties will always want slightly different timing and content, and that duplicate does not mean the same thing for a check-in event as it does for a booking. An if/else branch buried in one journey can fake the first for a while. It has no way to express the second at all, because there is nowhere on a shared trigger to put two different answers to what counts as one enrollment.
None of that is free. It is bounded by a real number of executions an hour. A claim mechanism keeps two workers from ever processing the same one twice, and a health check catches whatever got stuck when a worker crashed mid-step. A workflow builder for a hotel group has to hold all three at once, not just the part that looks good in a demo with one property open.
Twenty minutes, your real properties, no generic demo environment.