CelinQ Insights · No. 52
Why CelinQ Syncs in Seconds but Still Checks Every Minute
A fast event-driven sync path looks complete on paper. CelinQ runs three cadences underneath it, on purpose.
It is a reasonable question to ask of any synchronising system: if changes already propagate in a few seconds, why does the software also bother checking in once a minute, and again every five minutes on top of that? It looks, at first glance, like belt, braces, and a spare pair of braces for good measure — engineering caution that has tipped over into redundancy for its own sake. The honest answer is that the three cadences in CelinQ's Smart Sync are not three attempts at the same job. They are three different jobs, each catching a different way the world can go quiet, and none of them can be safely removed without leaving a gap that the other two do not cover.
The fast path does one job extremely well, and only that job
The fast path exists to make a healthy, connected editing session feel instantaneous to everyone watching. When an architect changes something in Enterprise Architect, the in-process CelinQ add-in hears the relevant EA event, signals the background agent over a local named pipe, and the agent debounces a short burst of such signals — by default a few seconds — into one coherent semantic changeset before pushing it to the server. The server, in turn, holds an open SubscribeChanges stream to every connected client in the workspace and pushes the committed changeset down that stream the moment it exists. In the common case, this is remarkably close to real time: a colleague working in the same workspace sees your rename, your new element, your adjusted tagged value, within a few seconds of you making it, without either of you doing anything to request it.
What the fast path is not, and was never designed to be, is a guarantee. It depends on a chain of individually reliable but not individually infallible components: the EA event actually firing, the add-in actually catching it, the named pipe actually delivering it, the agent actually being alive and listening, the network actually being up at that instant, and the server's notification stream actually staying connected to the recipient's client for the whole session. Any one of those links can fail on an ordinary day for an ordinary reason — a laptop that suspended briefly, a corporate proxy that closed an idle-looking long-lived connection, a moment where the EA COM automation layer hiccupped under load. None of these are rare or exotic. They are the background noise of running real software on real machines, and a design that pretended they would never happen would eventually be embarrassed by one of them in front of a client.
Why polling alone was never going to be enough either
It is worth pausing on the alternative that event-driven sync replaced, because the reasons it was replaced explain why a pure polling design would be equally wrong on its own. A system that only ever checked in on a fixed schedule — say, once every thirty seconds, regardless of what was happening — would deliver every change eventually, and it would never depend on a fragile notification stream staying open. But it would also mean that even in a healthy, fully connected session, a colleague's change could sit invisible for up to that whole interval before anyone else saw it, every single time, with no way to do better when conditions were good. Widen that interval to be gentle on the network and the invisible-change window grows with it; narrow it to keep the window small and you are back to hammering the server and the client's own machine with checks that, most of the time, find nothing new. Polling alone forces a single, fixed trade-off between promptness and overhead, and it forces every team to live with whichever point on that trade-off the interval happens to land on, whether their connection is excellent or terrible that day.
Event-driven sync is what lets CelinQ escape that fixed trade-off. When conditions are good, changes propagate in seconds because the system reacts to something actually happening rather than waiting for its next scheduled check. When nothing is happening, no traffic is generated at all — there is no changeset to debounce, so nothing is sent, and no notification stream has anything to push. It is a strictly better answer than fixed-interval polling in the case where it works. The reason CelinQ does not stop there is that "in the case where it works" is doing real load-bearing work in that sentence, and a design has to account honestly for the case where it does not.
An event-driven fast path and a fixed-interval safety net are not competing designs where you pick the better one. They fail in different ways, at different points, for different reasons — which is exactly why running both, at different timescales, closes gaps that running either one alone would leave open.
The sixty-second safety sync: a backstop that does not depend on anything else working
Once every sixty seconds, independent of whatever the event-driven path is doing, CelinQ's agent performs a safety synchronisation: it checks in with the server, confirms its local cursor matches where it should be, and pulls anything it might have missed. This layer is deliberately unglamorous. It does not try to be clever about which events matter or debounce anything into a coherent narrative; it simply asks the question "am I current?" on a fixed schedule and corrects course if the answer is no.
The value of that unglamorous design is precisely that it does not share a single point of failure with the fast path. If an EA event was missed — perhaps because the add-in's broadcast handler raced against a burst of automation calls, or because EA itself briefly stumbled under an unusually large batch operation — the fast path never learns anything happened, and no amount of waiting for a notification will fix that, because there is no notification coming. The safety sync does not care why the fast path missed something. It re-derives the current cursor position from the server independently, every sixty seconds, and any drift that has accumulated in that window gets caught and corrected. Equally, if the server's notification stream to a particular client silently dropped — the scenario where a corporate proxy or a sleeping laptop quietly closes a long-lived connection without either side immediately noticing — that client is not waiting for a notification that will never come. It will, at most, be sixty seconds behind before its own safety sync fires and reconnects it to reality.
Sixty seconds is not an arbitrary round number chosen for tidiness. It is short enough that the worst case — every layer of the fast path failing simultaneously for one client — costs that architect at most a minute of staleness, rarely enough to matter and rarely enough to notice, let alone to cause a serious conflict with a colleague's concurrent work. It is also long enough that running this check does not amount to continuous background chatter: a once-a-minute exchange is a negligible load on a healthy connection and a tolerable one even on a metered or intermittent connection, which matters because the safety sync has to keep working precisely in the degraded-network conditions where it earns its keep the most.
The five-minute deep reconciliation: catching what neither layer was watching for
There is a category of change that neither the event-driven fast path nor the sixty-second safety sync is well positioned to catch, because both of them are built around watching for signals — an EA event, a server notification, a cursor that should have advanced — rather than watching the repository's actual state. Someone might open the underlying .eap file with a tool outside CelinQ's normal path. A scripted bulk edit might touch hundreds of elements in a way that generates events faster than the add-in's throttling was tuned to expect. An agent process might be interrupted mid-operation and restart with a cursor that is technically valid but subtly stale. None of these situations necessarily produce the clean signal that the first two layers are listening for, because in each case the change did not travel through the channel either layer is watching.
Every five minutes, CelinQ runs a deep reconciliation: a full structural comparison of the current local repository against the last-known snapshot, built to surface drift regardless of how that drift occurred. This is deliberately the slowest of the three cadences, and deliberately so, because it is also the most expensive — comparing an entire repository's state is heavier work than debouncing one burst of events or confirming one cursor position, and running that comparison too often would cost more, in machine time and in disk activity, than the relatively rare drift it exists to catch is worth. Five minutes is the point where thoroughness and cost balance out: frequent enough that nothing stays silently wrong for the length of an entire working session, infrequent enough that it never becomes a background tax an architect can feel.
Layering these three timescales is the actual design, not a fallback plan
The property worth naming explicitly is that a missed event can never permanently lose a change. Any one of the three layers can fail, on any given day, for entirely mundane reasons, and the system still converges — because the next layer down operates on a different mechanism and a different timescale, and does not share whatever caused the layer above it to miss something. The fast path can fail because an EA event or a network notification did not arrive; the sixty-second safety sync does not depend on either of those and will catch it within a minute. The safety sync itself, in principle, only checks a cursor rather than the whole repository, so a change that produced no clean signal anywhere along that chain would not be visible to it either; the five-minute deep reconciliation does not depend on any signal at all, because it compares actual state rather than trusting that state was correctly announced.
This is why the honest way to describe Smart Sync's cadence is not "fast, with a slow fallback for when it breaks." It is three genuinely different mechanisms, deliberately operating at three genuinely different timescales, chosen so that no single class of failure — a missed EA event, a dropped notification stream, an out-of-band change to the repository — can go uncaught by all three at once. Decisions about exactly when each cadence fires are made by a small, pure, clock-injected scheduler component, kept deliberately simple and unit-tested precisely because the correctness of this layered design rests on the timing logic being exactly right and never accidentally coupled to any one layer's success or failure.
Missed EA events are not a hypothetical edge case
It is tempting to treat "the EA event might not fire" as a theoretical caveat included for the sake of completeness rather than a real operational concern, and it is worth being specific about why it is not. Enterprise Architect's event model was designed for a single desktop application talking to add-ins running in its own process, not for a background service that needs a perfectly reliable feed of every meaningful change. Bulk operations — a scripted import, a large paste, a model transformation run from the automation interface — can generate a flood of low-level events in a way that occasionally outpaces the throttling logic built to turn that flood into a manageable signal. A COM automation call issued at exactly the wrong moment relative to EA's own internal state can occasionally fail silently rather than raising the exception a defensive caller would expect. None of this reflects badly on EA; it reflects the ordinary reality of automating a mature desktop application that was never built with this exact integration pattern in mind, and CelinQ's engineering has to account for it rather than assume it away.
If CelinQ relied solely on the event-driven path, the consequence would be worse than a dramatic failure that announces itself: a specific change quietly never leaves the local machine, sitting in the repository, invisible to the fast path because nothing ever told it to look there, and invisible to the architect because their own local copy looks completely correct. Nobody would notice until a colleague asked why a change they were told about was not actually in the shared workspace, potentially days later, at which point the reconstruction of what happened is unpleasant for everyone involved. This is precisely the failure mode the sixty-second safety sync and the five-minute deep reconciliation exist to make structurally impossible rather than merely unlikely — not because missed events are common, but because the cost of one going permanently unnoticed is disproportionate to how rare it is.
External repository changes are the other blind spot
A second, related blind spot deserves its own mention because it does not involve any failure at all — it involves someone legitimately doing something CelinQ was never watching. Enterprise Architect repositories are, in the end, ordinary files or ordinary databases, and organisations have scripts, migration tools, and administrative processes that touch them outside of a live EA session with the CelinQ add-in loaded. A scheduled maintenance script might run a cleanup pass overnight. A database administrator might apply a schema-level fix directly. An architect might, briefly and for a specific reason, open the repository with a different tool entirely. In every one of these cases, the change is real, deliberate, and often entirely legitimate, but it happens through a path that never generates an EA event and never touches CelinQ's agent at all.
This is exactly the situation the five-minute deep reconciliation is built for and the other two layers are not, because both of the faster layers are, in different ways, listening for a signal that this kind of change never produces. The deep reconciliation does not ask "did something tell me to look here." It compares the repository's actual current state against what was last known, structurally, and treats any difference it finds as real regardless of its origin. That is a deliberately different kind of check from the other two, and it is the reason all three layers are necessary rather than any one of them, tuned more aggressively, being sufficient on its own.
What this looks like when something actually goes wrong
Picture an architect, Sofia, working through a Tuesday morning on a hotel's conference wifi — technically connected, in practice unstable, the kind of network that drops a long-lived connection every few minutes without ever fully disconnecting the laptop from the internet. Her EA events fire normally and her agent debounces and pushes changesets as usual; several of those pushes succeed cleanly over the flaky connection, and her colleagues see her updates within seconds, exactly as the fast path promises. At some point during the morning, the server's notification stream to her client quietly drops — the kind of silent failure a shaky wifi network produces routinely — and for a while she is not receiving her colleagues' updates as they happen, even though her own outgoing pushes are still occasionally getting through. She has no reason to notice this; nothing in her modelling session changes.
Within sixty seconds, her safety sync fires regardless of the dead notification stream, reconnects, and pulls in whatever she missed. If that particular sixty-second window happened to also fail — say the wifi genuinely dropped for the full minute — the next one tries again a minute later, and the one after that. At worst, Sofia works a few minutes slightly behind the shared state of the model, not because any layer of Smart Sync gave up, but because each layer is doing exactly the job it was built for: the fast path delivering promptly when it can, the safety sync correcting course every sixty seconds regardless of what the fast path managed, and the deep reconciliation standing by every five minutes to catch anything stranger than a dropped connection. The broader case for why this layered cadence exists at all — preventing conflicts rather than merely resolving them — is covered in the article on Smart Sync itself; this piece is really about why that prevention layer needed three different clocks rather than one clever one.
A system that is fast when everything works and silent when it does not is not resilient. It is untested. The value of the sixty-second and five-minute layers is precisely that they are boring, and boring is what you want underneath a fast path that has to keep working on real networks on ordinary days.
What this costs, stated plainly
Running three cadences instead of one is not free, and it would be dishonest to present it as a pure win with no downside. The sixty-second safety sync and the five-minute deep reconciliation both consume some machine time and some network traffic even when nothing has changed, because both are designed to check unconditionally rather than only when there is reason to suspect a problem. On a healthy, well-connected client that traffic is negligible — a small, regular check-in rather than a continuous stream — but it is not literally zero, and a design obsessed with minimising every last byte of background traffic might prefer to omit these layers and accept the occasional missed change as a cost of doing business. CelinQ's judgement is that the cost of a quiet, periodic check-in is small and predictable, while the cost of a silently orphaned change — the kind that erodes trust in the whole system the day someone discovers it weeks later — is neither.
There is also a genuine limit to how far this layered approach can be pushed before it starts working against itself. Tightening the sixty-second interval to, say, ten seconds would shrink the worst-case staleness further, but it would also multiply the background traffic by six for a benefit that matters only in the relatively rare case where the fast path has already failed. The five-minute deep reconciliation could in principle run every thirty seconds instead, but a full repository comparison at that frequency would start to be felt as real overhead rather than an invisible background task, on exactly the machines — laptops on trains, machines on metered connections — where keeping overhead low matters most. The defaults reflect a judgement about where these trade-offs sit for typical CelinQ workspaces, not a claim that they are the only numbers that could ever be correct; teams with unusual patterns of contention or unusual network conditions are exactly the kind of case where Hot Collaboration's tightened cadence for a genuinely busy diagram exists as a deliberate departure from the defaults rather than a universal tightening of them.
The plain summary is this: the fast path is what makes CelinQ feel responsive on a good day, and it is genuinely fast — most changes really do arrive within seconds. The minute-by-minute safety sync and the five-minute deep reconciliation are not there because the fast path is untrustworthy in some ordinary sense. They are there because no single mechanism, however well built, can be relied upon never to have a bad day, and a synchronisation design that is honest about that builds in more than one way to notice when it has. The same layered thinking is what makes offline work safe rather than merely convenient — the queue that holds your changes while you are disconnected is simply what the fast path looks like when, for a while, there is nowhere for it to push to, and the safety and reconciliation layers are what make sure that gap closes cleanly once the network returns.