CelinQ Insights · No. 51
Preventing Enterprise Architect Conflicts Before They Happen with Smart Sync
Most conflict-resolution engineering makes collisions survivable. Smart Sync's quieter goal is making them rarer in the first place.
A conflict between two architects working on the same Sparx Enterprise Architect model is, in the overwhelming majority of cases, not a disagreement about architecture. It is a scheduling accident. Two people happened to touch the same element, at roughly the same time, while each was unaware of what the other was doing, and by the time either of their changes reached anywhere the other could see it, the two versions had already diverged. Resolve that conflict as elegantly as you like — and a good deal of this series is about exactly that — and you have still spent a decision on something that, with slightly better timing, would never have needed one. Smart Sync is CelinQ's answer to a narrower and more preventable question than "how do we merge two incompatible changes." It asks: how do we shrink the window in which two changes can become incompatible in the first place, without ever asking the architect to wait for the network to agree.
This distinction between prevention and resolution matters more than it might first appear, because the two are often discussed as if they were the same engineering problem wearing different clothes. They are not. Conflict resolution is what happens after two people have already diverged: it takes two incompatible states of the world and produces one coherent state, ideally with as little human judgement spent as possible and none of it wasted on things that were never really in dispute. Conflict prevention is what happens before that point is reached at all. It does not make merges smarter. It makes divergence smaller, so that fewer merges ever need to be smart about anything. A team that only ever invests in resolution is optimising the wrong end of the problem — it is getting very good at cleaning up a mess it could, in a large share of cases, have avoided making.
Why local-first collaboration needs a prevention layer at all
It is worth being honest about why this problem exists in CelinQ's architecture and did not exist, in quite the same form, in a traditional shared-repository setup. A centrally hosted Enterprise Architect repository prevents divergence structurally: every read and every write goes through the one authoritative store, so there is, at any instant, only ever one version of the model to speak of. The price of that guarantee is that every operation pays the cost of a round trip to wherever that store happens to live, and the model stops being editable at all the moment the network to that store is unavailable. CelinQ takes the opposite trade. Each architect works against a local EA repository that is fully theirs, fully fast, and fully usable offline, and a background agent — CelinQ Connect — carries changes to and from a shared workspace on the organisation's own server asynchronously. That is what makes the modelling experience fast and resilient. It is also what creates a window, however brief, during which two architects' local repositories can legitimately disagree with each other and with the server, simply because neither of their changes has arrived at the other's machine yet.
Smart Sync exists to make that window as short as it can reasonably be made without reintroducing the thing local-first was designed to remove: a dependency on the network for ordinary editing. The constraint is strict and non-negotiable. Nothing in Smart Sync ever makes an EA read or an EA write wait on a server response. Every mechanism described in this article runs beside the modelling session, not inside it. The architect who is typing, dragging a connector, or renaming a package never feels Smart Sync at all; what they feel, if the design works, is that their colleagues' changes tend to show up sooner than they might expect, and that the model rarely surprises them with a conflict they had no warning of.
The fast path: event-driven changes and a debounce that respects a burst of work
The first and most visible layer of Smart Sync is event-driven. Enterprise Architect broadcasts events as an architect works — an element created, a property changed, an object deleted — and CelinQ's in-process add-in listens for exactly the events that matter, throttling them into a signal on a local named pipe that the background agent watches. The moment that signal arrives, the agent knows something has changed and begins the process of turning it into a coherent semantic changeset to send onward.
The word "moment" needs a small qualification, and it is a deliberate one. If the agent pushed a changeset to the server after literally every single EA event, a routine five minutes of renaming, re-parenting, and tidying up tagged values would generate dozens of tiny revisions, each one a fragment of a train of thought that made no sense in isolation and that would arrive at a colleague's machine as noise rather than information. So the agent debounces: it waits a short window, by default a few seconds, for the burst of activity to settle, and only then packages everything that happened in that window into one semantic changeset and pushes it. The debounce is not a delay imposed for the network's convenience; it is what turns a scattershot of low-level EA events into something that reads, on the receiving end, the way an architect actually thinks — a handful of related decisions made together, not a keystroke-by-keystroke transcript.
Once that changeset leaves the local agent, it goes to the server immediately, and from there the server's own fast path takes over. Connected clients hold an open SubscribeChanges stream to the server, and a committed changeset is pushed down that stream to every other client working in the same workspace as soon as it is recorded — not on their next poll, not on their next scheduled sync, but as a notification the moment the server has it. In a healthy, connected team, this is the mechanism that does most of the actual prevention work: an architect who renames a package a few seconds ago has, by the time a colleague opens that same package, already had their change arrive. The colleague never had the chance to start editing a version of the model that was already out of date, because the update reached them before their attention did.
Prevention, in this design, is not a promise that two people will never touch the same thing. It is a bet, engineered rather than hoped for, that most of the time one person's change will have already arrived before the other person starts theirs — and that when the bet does not pay off, the resulting conflict will be small, because the divergence window was measured in seconds rather than hours.
The safety net: a minute is short enough to matter and long enough to be cheap
An architecture that relied purely on events and notifications would be elegant on a whiteboard and fragile in practice, because both halves of that fast path can fail in ordinary, unremarkable ways that have nothing to do with malice or misconfiguration. An EA event can be missed — a race between the add-in and a particular sequence of automation calls, an EA session that hiccupped, a notification that the operating system's own pipe delivery silently dropped. A server notification can fail to arrive — a laptop that went to sleep mid-stream, a corporate proxy that quietly closed a long-lived connection it decided had been idle too long, a brief network blip that happened to land exactly on the one packet that mattered. None of these are exotic failure modes. They are the ordinary background noise of real machines on real networks, and a design that assumed they would never happen would eventually be embarrassed by one of them at the worst possible moment — in front of a client, during a deadline, on the one day the demo needed to work.
Smart Sync's answer is a second layer that does not depend on either the event system or the notification stream working correctly: a safety synchronisation that runs on a fixed cadence, by default once every sixty seconds, regardless of whether any event fired and regardless of whether any notification arrived. Once a minute, independently of everything else, the agent checks in with the server, confirms its cursor is where it should be, and picks up anything it might otherwise have missed. A minute is a carefully chosen number rather than an arbitrary one. It is short enough that a missed event or a dropped notification costs an architect, at worst, sixty seconds of staleness — not the kind of gap in which serious divergence has time to build up, and rarely even a gap anyone notices. It is also long enough that running this check does not amount to a background poll aggressive enough to matter on a metered connection or a loaded server. The safety sync is not there to be fast. It is there to be a backstop that never depends on the thing it is backing up.
The deep layer: five minutes to catch what neither of the other two could see
There is a category of drift that neither the event-driven fast path nor the sixty-second safety sync is well positioned to catch, because both of them are, in different ways, watching for signals rather than watching the repository itself. Someone might open the underlying .eap file directly and make a change outside CelinQ's normal path. A restore, a scripted bulk edit, or an interrupted agent process might leave the local cursor pointing somewhere slightly wrong. None of these produce the kind of event or notification the first two layers are built to react to, because in each case the thing that changed did not announce itself through the channel either layer is listening on.
Every five minutes, CelinQ runs a deep reconciliation: a full comparison of the current state of the local repository against the last-known snapshot, structured to surface anything that has drifted regardless of how it got there. This is deliberately the slowest and least frequent of the three layers, because it is also the most thorough, and thoroughness at this scale is not free — scanning a whole repository for drift is a heavier operation than debouncing an event or checking a cursor, and running it too often would cost more than the drift it occasionally catches is worth. Five minutes is the balance point: frequent enough that nothing stays silently wrong for an entire working session, infrequent enough that it never becomes a tax on the machine it is protecting.
The property that actually matters, and the one worth stating plainly, is this: a missed event can never permanently lose a change. Any single layer of Smart Sync can fail on any given afternoon — an event can be swallowed, a notification can be dropped, a connection can flap — and the model still converges, because the layer beneath it will eventually notice and correct course. The three layers are not three attempts at the same job stacked for redundancy's sake alone; they operate at genuinely different timescales and catch genuinely different failure modes, and it is the combination, not any single layer, that gives Smart Sync the property that no realistic sequence of missed signals leaves an architect's work permanently orphaned from the rest of the team.
What this looks like on an ordinary Tuesday
Consider two architects, Elke and Tomas, both extending the same subsystem of a model over the course of a morning. Elke starts by renaming a package and adjusting a handful of tagged values on three elements inside it. She pauses for a moment to think, and in that pause the debounce window closes and her agent pushes a changeset. Because Tomas's client holds an open notification stream to the same workspace, his EA session receives the update within moments — before he has opened the package Elke was working in. When he does open it a few minutes later, he sees Elke's renamed package and her updated tagged values already in place, and he starts his own work from a model that already reflects hers. No conflict occurred, not because the tool got lucky, but because the fast path did what it was built to do: it closed the window before Tomas's attention reached the same corner of the model.
Now vary the story slightly. Tomas is on a client site with a guest network that intermittently drops long-lived connections, and his notification stream silently disconnects without either of them noticing. He opens the same package a few minutes after Elke saved, working from a version of the model that is now sixty seconds or so behind hers, because his sixty-second safety sync has not yet had its next turn. If he makes a change to the same element Elke touched inside that narrow window, a genuine conflict is possible — but it is a conflict born of a window measured in tens of seconds, not the hours-wide window that would have existed if the safety layer were not there running quietly underneath the notification stream that failed him. When that safety sync does fire, moments later, it recovers his connection and folds in Elke's update, and if the two of them really did touch the same fact, Fusion will isolate exactly that fact for a decision rather than anything either of them left untouched.
A third variant: Elke works from a train for forty minutes with no connectivity at all. Nothing about Smart Sync changes from her side — she edits, EA fires its events, the add-in signals the agent, the agent debounces, and changesets queue up locally exactly as they would if she were online, because nothing about local editing in CelinQ ever depends on the network being present. The difference is only in where the changesets go: instead of reaching the server within seconds, they sit in a durable local queue, safely journaled to disk before any network attempt is made, waiting. When the train re-enters coverage, the agent resumes exactly where its cursor left off and replays the queue, and the server applies each changeset in order, exactly as if the delay had never happened. The way this cadence adapts to different conditions is its own subject, but the short version is that offline is not a separate mode Smart Sync has to detect and switch into. It is simply what the fast path looks like when there happens to be nowhere to push to yet.
Reconnection is where prevention hands off to reconciliation honestly
It would be dishonest to present Smart Sync as eliminating conflicts, and it does not claim to. What it changes is the shape of the conflicts that do occur. Without any prevention layer at all — if every architect worked entirely offline for hours and synchronised only occasionally by hand — a team would routinely face large, tangled divergences: dozens of changes on each side, overlapping in ways that are hard to reason about because so much time separated the moment two people's work started to differ from the moment anyone noticed. With Smart Sync's three layers running continuously in the background, the ordinary case is that divergence windows stay small — seconds during active connectivity, at most a few minutes during a genuine outage — so that when reconnection does happen and a real conflict does surface, it tends to be small, recent, and easy for a person to reason about, rather than an archaeological dig through half a day of parallel work.
That handoff to reconciliation is deliberate and it is not hidden. Smart Sync's job ends the moment a genuine, simultaneous, incompatible edit exists — two architects who really did change the same property of the same element within the same narrow window, faster than any of the three layers could have propagated one change before the other began. At that point, prevention has done everything it usefully can, and the problem becomes a question for CelinQ's Fusion merge engine, which handles it deterministically and without guessing, exactly as described elsewhere in this series. Smart Sync leaves that adjudication to Fusion. Its value lies in narrowing how often the handoff has to happen — nothing more, and nothing less.
The right way to judge a synchronisation design is not by how cleverly it resolves the conflicts that reach it. It is by how few conflicts it lets reach that point in the first place, without ever making the person doing the modelling wait to find out.
Trade-offs worth naming honestly
None of this is free, and a design that pretended otherwise would not deserve much trust. The debounce window that turns a burst of edits into one coherent changeset is also, by definition, a small delay before that changeset leaves the local machine — a few seconds during which, in principle, someone else could start editing the same element without yet seeing the change. Widening the debounce to batch more work together would only widen that exposure; narrowing it toward zero would recreate the noisy, keystroke-level chatter the debounce exists to prevent. The default sits where engineering judgement says the trade-off is best, but it is a genuine trade-off, not a solved problem.
The sixty-second safety sync and the five-minute deep reconciliation are deliberately not instantaneous, and that is also a choice with a cost. A team that needs sub-second guaranteed consistency between every pair of clients, regardless of what layer of Smart Sync is doing the work at that instant, is asking for something closer to a centrally locked repository than to a local-first one, and should weigh that need honestly against the offline resilience and full local speed that local-first buys in exchange. And no amount of prevention engineering changes the fact that two architects can, on occasion, deliberately and knowingly want to work on exactly the same element at exactly the same time — a pairing session, a live workshop, a diagram both of them are actively shaping together. For that specific situation, prevention through timing is the wrong tool, which is precisely why CelinQ has a separate mode, Hot Collaboration, that detects sustained contention on one diagram and changes its behaviour deliberately rather than trying to out-run it with a shorter debounce.
What Smart Sync does deliver, honestly and without overstatement, is a system that never asks an architect to wait for the network, that keeps the ordinary divergence window small enough that most potential conflicts never get the chance to become real ones, and that fails safely — through a layered design where no single missed signal can permanently strand a piece of work — when the ordinary case does not hold. That is a more modest claim than "no conflicts," and it is the honest one. The presence layer that shows who else is working where builds on the same premise Smart Sync establishes here: that the network should decide how quickly your work reaches your colleagues, never whether you are allowed to do it.