Migrating from Sparx Enterprise Architect: A Practical Guide
Every EA tool migration starts with someone asking a version of the same question: "can we just export the diagrams and import them somewhere else?" The honest answer is no, and the reason why is the whole subject of this article. A diagram is the least valuable thing to move. What actually has to survive the trip is everything the diagram was standing in for — the elements, the relationships between them, the folder structure the repository was organized around, the tagged values and custom properties someone spent two years filling in, the documentation fields, the stereotypes, and in the case of native UML classes, their attributes and operations. Get that part right and the diagrams mostly take care of themselves. Get it wrong and you've built a nice-looking picture of nothing.
This is a guide for a team that already has a working Sparx Enterprise Architect repository — often years old, often the single source of truth for an application landscape or a public-sector reference architecture — and is considering moving some or all of that work into Mooodels, either as a full migration or as a parallel, web-based front end that coexists with Sparx for a while. We built the interoperability layer between the two tools, so this isn't a neutral third-party comparison. It is, however, a genuinely practical one: what moves cleanly, what doesn't, where the sharp edges are, and why a phased rollout beats a weekend cutover every time.
What "migrating" actually has to cover
It's worth being explicit about this because it's where migrations quietly go wrong. "Migrate the Sparx repository" sounds like one task. It's really at least seven, and they don't all move through the same mechanism or carry the same risk:
- Elements — applications, business functions, actors, data objects, whatever your profile defines. This is the easy part; every tool agrees on the idea of a named, typed thing.
- Relationships — the connections between elements: uses, serves, realizes, triggers, and so on. This is where fidelity actually gets tested, because relationship semantics differ between metamodels and because relationships can themselves get exotic (more on that below).
- Folder and package structure — the organizational hierarchy the repository has been built around, often reflecting how a specific team or programme thinks about the portfolio. Losing this doesn't lose data, but it loses years of accumulated organizational sense-making, and nobody wants to rebuild that by hand.
- Diagram layout — node positions, styling, z-order, which elements are grouped visually. Not semantically load-bearing, but it's what makes a diagram immediately legible to someone who has looked at it a hundred times. A correct-but-rescrambled diagram is technically fine and practically useless in a workshop.
- Documentation fields — free-text notes attached to elements, often containing the only written rationale for a decision that exists anywhere.
- Tagged values and custom properties — the extension mechanism every serious Sparx repository ends up leaning on, because the built-in metamodel never quite covers what one particular organization needs to track.
- Stereotypes and specializations, and for native UML classes, attributes and operations — the parts of a class diagram that carry real structural meaning, not just decoration.
A tool that only handles the first two items on that list and calls it a migration has handed you a skeleton. Everything that made the repository worth using — the notes, the tags, the layout people navigate by, the class structure a data architect actually reads — is exactly the part that's hardest to carry across, and exactly the part most migration tooling quietly drops.
How the exchange actually works
Mooodels doesn't talk to Sparx EA directly over COM from the browser, and it doesn't try to parse the EA project file. Both of those are viable engineering choices in isolation, but they tie you to a single direction of travel and make round-tripping — importing, editing, and re-exporting back into the tool you started with — much harder to reason about. Instead, the two tools meet in the middle, through a shared interchange that each side knows how to produce and consume.
On the Sparx side, a pair of scripts drives the exchange against the EA repository through its scripting interface: one walks the repository and produces an export, the other reads an export and applies it back. On the Archi side, a matching pair of jArchi scripts does the same thing against an Archi model. The web side produces and consumes the same exchange. One mechanism, three tools, no per-pair translation layer invented for each new combination.
What the exchange carries is described entirely in terms of the model, not in terms of presentation: the identity of every object, its type and name, its documentation, its tagged values, its position in the package hierarchy, the endpoints and direction of every relationship, the stereotypes applied to it, the attributes and operations of native UML classes, and the geometry of every diagram — which shapes appear on it, where they sit, how big they are, how they're layered, and which connectors run between them. That list is the contract. If something on it goes missing across a round trip, that's a defect. If something not on it changes, that's expected behaviour, and the table further down says so explicitly.
The exchange is also deterministic: the same model produces the same export every time, with stable ordering and stable identifiers rather than whatever sequence the source tool happened to iterate in that day. That property is quietly load-bearing for verification. It means two exports taken a month apart can be compared directly and the difference is exactly the set of changes people made — not a wall of reordering noise you have to read past to find the one edit that matters. It's also what makes keeping exports under version control worth doing at all, rather than an exercise in committing churn.
The important design decision buried in that diagram is that the exchange isn't a lossy lowest common denominator. It's closer to a superset: it carries not just the things the canonical model has native concepts for, but also the things it doesn't, wrapped in what we call a round-trip envelope. A stereotype, a UML operation signature, a diagram's exact node coordinates, a tagged value attached to the model root rather than to any element — none of these are things the canonical model needs to understand semantically in order to preserve them faithfully. They travel through as structured payload, get stored against the object they belong to, and come back out unchanged on export, even though nothing in its own object model ever "knew" what a UML operation was for. That's a deliberate choice: better to carry data you don't natively reason about than to silently drop it because it doesn't fit your metamodel.
What round-trips cleanly, and what doesn't
Every migration tool has a boundary, and the honest way to talk about one is to draw it precisely rather than imply it doesn't exist. Here's the practical picture for a real, round-trip exchange:
| Data | Round-trips | Notes |
|---|---|---|
| Elements and their types | Cleanly | Preserved with EA GUID as source identity. |
| Standard relationships | Cleanly | Uses, serves, realizes, association, and similar — mapped both directions. |
| Folder / package hierarchy | Cleanly | Structure is carried as part of the exchange, not inferred afterward. |
| Diagram geometry (position, styling, z-order) | Cleanly | Stored in the round-trip envelope even though the canonical model doesn't natively need coordinates. |
| Tagged values / custom properties | Cleanly | Carried as properties on the element; arbitrary keys survive. |
| Root-level tagged values on the model itself | Cleanly | Version stamps, owning department, reference-architecture edition — carried in the round-trip envelope. |
| Stereotypes and specializations | Cleanly | Preserved via the round-trip envelope, applied against the active profile on re-render. |
| UML attributes / operations on native EA classes | Cleanly | Signatures and types are preserved even without a native canonical-model concept for them. |
| Documentation / notes fields | Cleanly | Mapped to the equivalent free-text field on the receiving side. |
| Relationships with a relationship as an endpoint (ArchiMate 3.1) | No | Not representable in the canonical model or in EA's own object model consistently; skipped with an explicit warning on both sides. |
| Tool-specific rendering quirks (custom shape scripts, MDG-specific icon overrides) | Partial | Geometry and standard styling survive; a fully custom shape script is a Sparx-only concept with no equivalent to preserve. |
| EA "model views" built from saved searches / dynamic queries | No | These aren't diagrams in the exchanged sense — they're live queries against the EA repository and don't have an export target. |
The one limitation worth calling out by name, because it trips people up precisely because it sounds like an edge case and then turns out to matter to one specific team's model, is relationships whose endpoint is another relationship. ArchiMate 3.1 introduced the ability to attach a relationship not just to an element, but to another relationship — useful, for instance, for expressing that an influence relationship is itself the target of an association, in some fairly advanced motivation modelling. Neither the canonical model nor, in practice, a consistent object-level representation inside EA itself treats a relationship as a first-class thing that other relationships can point at without ambiguity. When the export encounters this pattern, it doesn't silently drop it and it doesn't guess at an approximation — it skips the relationship and writes an explicit warning into the export log, on both the Sparx side and the Archi side. You'll see it. It won't show up in your model as a broken reference or a mysteriously vanished connector; it shows up as a line in the log telling you exactly what wasn't carried over and why.
Why re-importing doesn't duplicate everything
The single most common fear about round-tripping between two tools is duplication — export from Sparx, import into the target model, make some edits, export from Sparx again a month later after someone else has been working in it, and now you've got two of everything. This is where GUID-based identity does the actual work.
When an element is exported from Sparx, it carries the element's EA GUID along as its source identity — not as a tag, as the thing the importing tool uses to recognize "this is the same object" on any subsequent import. The first import creates a new element in the canonical model and records that GUID against it. The second import, three weeks later, after the Sparx side has had five more relationships added to it, doesn't create five new elements plus duplicates of everything that already existed — it matches every incoming object against its recorded GUID, updates the ones that changed, adds the ones that are genuinely new, and leaves everything else alone. A rename on the Sparx side is a rename on the other side too, not a delete-and-recreate, because the GUID — not the display name — is what identity is anchored to.
Where no source identity exists, matching falls back to name plus type: an incoming Application Component named "Payment Gateway" is treated as the same object as an existing Application Component named "Payment Gateway", but not as the same object as an Application Service with that name. That fallback is deliberately conservative, because in a real portfolio the same word legitimately names several different things at different layers, and collapsing them would be a far worse failure than creating one duplicate. It's the safety net for content that has never been through a round trip, not the primary mechanism — anything that has crossed once is matched on identity from then on.
This matters more than it might sound like it does, because it's the property that makes "run both tools in parallel for a while" a viable strategy instead of a data-integrity risk. If every re-import duplicated the model, parallel operation would be unworkable within a month — you'd be manually deduplicating hundreds of elements every time someone wanted a fresh sync. GUID matching is what turns re-import from a one-time migration event into a repeatable operation you can run on a schedule, or on demand, without dread.
It's worth being precise about the direction this holds in. GUID matching works cleanly for objects that originated in Sparx and are being kept in sync. An element created natively on the web side and exported back to Sparx for the first time doesn't have an EA GUID yet — EA generates one on creation, same as it always has, and from that point forward the same matching mechanism applies to it too. The identity anchor isn't something either tool has to negotiate case by case; it's simply whichever GUID space the object was born into, tracked consistently from then on.
How to verify fidelity on your own repository
Everything above is a claim, and claims about migration fidelity should be tested against your content rather than accepted on the strength of a table. The test is cheap — an afternoon on a copy — and it converts a general assurance into a specific answer about your repository.
- Count before you start. Record element, relationship, package, and diagram counts from the Sparx side, plus the number of distinct tagged-value keys in use. These four or five numbers are what you'll compare everything against.
- Import, then compare counts. Any discrepancy at this stage is worth chasing before you look at anything else, because a count mismatch means something outside the documented boundary happened.
- Read the warning log rather than skimming it. This is where relationship-to-relationship cases, dynamic model views, and custom shape scripts announce themselves. Each line is a decision someone has to make, not noise to scroll past.
- Open the three diagrams you'd least like to see degraded. Usually the ones that appear in governance packs. Check that layout, grouping, and labels are recognizable — not merely that the right elements are present.
- Check the tags that governance depends on. Pick the two or three tagged-value keys your processes actually consume — lifecycle state, owner, criticality — and confirm the values are intact on a sample of elements, including elements where the value is empty rather than set, which is a distinction that's easy to lose.
- Export back to Sparx and re-import. The round trip isn't verified until the model has gone out and come back. Counts after the second import should be identical, not doubled — that's the test of identity matching on your own content.
- Make one small edit on each side and sync. Rename an element in Sparx, change a documentation field on the web side, sync, and confirm both edits landed on the intended object rather than producing a near-duplicate. This single test tells you more about whether parallel operation will work than any amount of reading.
If all seven steps come back clean and the only reported losses are the ones the table above predicts, you have a verified pipeline rather than a hopeful one. If anything falls outside the documented boundary — a dropped tag, a relationship that changed type, a truncated notes field — that's a real finding, and it's much better to have it in an afternoon on a copy than in month three on the production repository.
Putting the migrated model under version control
Sparx repositories are typically kept in a database or a project file, which means history lives inside the tool, if it's kept at all. One of the more understated benefits of moving to a canonical model is that the model becomes something you can keep in Git alongside everything else the organization versions.
Because serialization is deterministic and identifiers are stable, a diff between two commits reflects the edits people made and nothing else. Adding one relationship shows up as one relationship added. Rewriting the documentation on a business function shows up as that field, on that element, changed. That's what makes a model reviewable the way code is reviewable: an architect who wasn't in the session can read the change, comment on it, and approve it without opening a modelling tool at all.
For a migrating team, the concrete advice is to commit the very first import untouched, before anyone edits anything, and treat that commit as ground truth. Every subsequent change — made on the canvas, proposed by AI as a patch and accepted, or arriving from a fresh sync off the Sparx side — lands as a diff against a known baseline. Six months later, "what has actually changed since we migrated" is a question with an exact answer rather than an archaeology project.
A realistic phased approach
Given all of that, here's the sequence that actually works, as opposed to the one that looks faster on a slide.
Phase 1 — import once, on a copy
Run the export from Sparx and the import into the target model against a real project, but not the production repository everyone depends on for daily work. The goal of this phase is entirely diagnostic: does the folder structure come across the way you expect, do the tagged values you actually rely on survive, does a diagram someone knows well look recognizable, and — critically — what shows up in the warning log. A repository that's been alive for six or eight years has accumulated things nobody remembers adding: an orphaned stereotype from a metamodel that got retired, a relationship type nobody uses anymore, a custom MDG technology someone installed for a project that ended in 2019. This phase surfaces all of that before it's anyone's emergency.
Phase 2 — verify fidelity against a real, opinionated audience
Don't verify a migration by eyeballing it yourself. Put the imported model in front of the person who actually maintains the Sparx repository day to day and ask them to try to break it — find the diagram that looks wrong, the tag that's missing, the relationship that doesn't mean what it used to. This is also the phase where you decide, deliberately, what to do about anything in the warning log: is it genuinely unused and safe to leave behind, or does someone need to remodel it using a supported construct before the real migration happens. This step is boring and it's also the entire point — it's the difference between a migration that gets trusted and one that gets quietly reverted three weeks after go-live because someone found one bad diagram and stopped believing the rest.
Phase 3 — run both tools in parallel
Once fidelity is verified on real content, don't cut over immediately. Keep Sparx as the system of record for a defined period — a sprint, a quarter, whatever matches how your organization actually works — while people start using the new tool for day-to-day editing, diagramming, and review. Re-import from Sparx periodically, or on demand, using the same GUID-matched mechanism from phase 1, so the two stay in sync without manual reconciliation. This is the phase that actually builds trust, because it's lived experience rather than a one-time test: does re-import keep behaving the way it did in phase 1 once real people are making real changes on both sides, and does anyone hit a limitation from the round-trip table above that actually affects their work, as opposed to one that was theoretical.
Phase 4 — cut over once trust is earned, not scheduled
Only move Sparx to a read-only archive, or retire it outright, once the parallel period has actually demonstrated that nothing important gets lost and nobody's workflow is silently broken. This is not a milestone to put on a project plan with a fixed date attached before phase 3 has told you anything. It's a decision you make when the people who'd notice a problem have stopped finding one.
The riskiest architecture migrations aren't the ones that go wrong. They're the ones where nobody would have known if they had, because the old system was switched off before anyone had a chance to compare.
A phased approach costs more calendar time than a big-bang cutover. It also means that if something surfaces in month two that wasn't visible in the initial test — a class of relationships nobody thought to check, a tag pattern used inconsistently across the portfolio — you find out while the old system is still sitting there as ground truth, rather than after it's gone.
What this is not
It would be easy to write the rest of this article as though the exchange and GUID matching solve migration completely, and that would be dishonest. A few things worth saying plainly:
This is not a magic button. Someone still has to run the export, review the warning log, decide what to do about anything that didn't round-trip, and — this is the part that's easy to underestimate — actually look at the result critically rather than assume a green checkmark means correctness. A tool that faithfully carries across a model that was already inconsistent will faithfully hand you an inconsistent model somewhere else. Migration is a good moment to clean up structural debt precisely because you're already reviewing everything, but the cleanup is still work a person has to do.
It's also not one-directional in a way that lets you treat the web side as a disposable viewer. Because the exchange genuinely round-trips, changes made there can flow back into Sparx through the same mechanism — which is good for parallel operation, but it does mean both sides need to understand, during the parallel phase, which tool is authoritative for which piece of work at any given moment, so two people don't independently edit the same element in two tools between syncs. That's a process discipline question, not a tooling limitation, but it's real and worth agreeing on explicitly before phase 3 starts, not after the first conflict.
And it's not free of the relationship-to-relationship limitation, or others like it that a specific organization's modelling style might surface. The honest promise isn't "everything moves perfectly." It's "everything that can move, moves with full fidelity — elements, relationships, folders, layout, documentation, tags, stereotypes, and UML structure alike — and everything that can't is flagged loudly enough that it becomes a decision, not a silent loss."
Where this leaves a team deciding whether to move
If the question is "can we get our Sparx repository into Mooodels without losing what we've built," the answer for the overwhelming majority of a typical EA repository is yes — not as a one-time export that hopes for the best, but as a repeatable, GUID-matched sync that you can run once to test, run again to verify, and keep running for as long as it takes to trust the result. The relationship-to-relationship case and a handful of genuinely tool-specific rendering features are the honest exceptions, not evidence that the rest is shaky.
What actually determines whether a migration like this goes well isn't the fidelity of the export mechanism — that part is deterministic and it either works or it visibly doesn't. It's whether the team gives phase 2 the attention it deserves, and whether anyone has the discipline to run phase 3 for long enough to mean something before declaring victory. The tooling can make round-tripping safe. It can't make the verification step optional, and it shouldn't try to.
See the model this article describes, working in a real editor.
Try the live demo