Home / Blog / Migration & Interoperability

What to Check Before Trusting an Architecture Import

An import that finishes without an error has told you exactly one thing: the importer did not crash. It has not told you that your architecture arrived intact. Those are different claims, and the gap between them is where quiet damage accumulates — a tagged value nobody misses until an audit asks for it, a package hierarchy flattened into one long alphabetical list, four hundred relationships that quietly became three hundred and ninety-one. The importer was honest. It said "success." You heard "correct."

This article is about the hour after the import completes and before you start relying on the result. That hour is cheap. Rebuilding trust in a model six months later, after three people have edited it and nobody remembers what the source looked like, is not. What follows is a concrete checklist — what to verify, how, and what a failure looks like when you find one — plus an honest account of why no importer between genuinely different metamodels is lossless.

Why "success" is such a weak signal

Import tooling reports on the thing it can measure, which is its own execution. It parsed the file. It reached the end. It wrote objects. None of those facts say anything about semantic fidelity, because the importer has no independent notion of what your architecture was supposed to mean. It only knows what it managed to read.

Consider the ways an import can succeed loudly and fail silently. A relationship type with no counterpart in the target metamodel gets mapped to the nearest available thing, so the count reconciles while the semantics shift underneath you. A documentation field lives in a property the importer doesn't look for, so every element arrives with a name, a type, and an empty description. A folder tree that encoded ownership — one package per directorate, because that's how the organisation is actually shaped — becomes membership metadata on a flat list, technically the same information and practically unusable in the view where it mattered. A nested element gets promoted to a sibling. Every one of these is a green run.

The reframe: treat an import the way you'd treat a database migration, not the way you'd treat opening a file. Migrations get a pre-check, a post-check, a reconciliation, and a documented rollback. Nobody runs one and says "no errors, ship it."

Before you import: capture the baseline

Verification is comparison, and comparison needs something to compare against. The most common reason people skip reconciliation is that they never wrote down what the source contained, so afterwards there's nothing to reconcile to except a vague sense that it was "about a thousand things."

Spend ten minutes in the source tool first. In Sparx Enterprise Architect, project statistics and a couple of model searches give you counts by element type, connector type, package and diagram; in Archi, the model tree and validator give you the same shape of information. Write it into a scratch file. At minimum:

That last item is the one people skip and the one that catches the most. Random sampling of a large model mostly re-confirms that ordinary elements imported fine. Deliberate sampling of the weird ones is where the information is.

Check one: reconcile the counts, by type

Start with arithmetic, because it's fast and it's unambiguous. Compare your pre-import baseline against what the target reports. Totals matching is a good start. Totals matching per type is a much stronger signal.

Watch specifically for the two directions of drift. Fewer objects than the source means something was dropped or skipped — usually a type that couldn't be mapped, or objects that failed validation and were quietly excluded. More objects than the source is the more interesting failure, and it usually means the importer materialised something implicit: a nested element promoted to its own object, a diagram-only shape treated as a real element, or a connector that was represented once in the source but twice in the target because it appeared on two diagrams.

Relationships deserve a second pass on their own, because that's where metamodel differences bite hardest: a relationship carries a type, a source, a target and often a direction, and all four have to survive. A count that reconciles perfectly on elements but is short a dozen on relationships is telling you something specific — a relationship type in your source has no clean mapping. Find out which one before going further.

If your source model has views, count objects on the largest one and compare. A view that arrives with the right name and forty of its sixty-one objects is a failure that no total-level count will ever reveal.

Check two: spot-check the payload, not the labels

Names and types survive almost every import, because they're the two things every metamodel has. That's exactly why checking them proves so little. The interesting content is everything hanging off the object: documentation, tagged values, owners, lifecycle status, criticality ratings, the reference number that ties the element back to a CMDB entry.

Pick your sample deliberately. A good sample of ten looks like this:

Ten lookups takes about fifteen minutes and finds more than an hour of aimless clicking. And when something's missing, you now know which mechanism failed, not merely that "some stuff seems off."

Check three: confirm the structure survived, because it meant something

Folder and package hierarchy is routinely dismissed as cosmetic, and it almost never is. In real repositories the tree encodes something: one package per business domain or per directorate, a separation between as-is and to-be, a quarantine folder for elements pending review. It is often the only place certain organisational facts are recorded at all.

The canonical model underneath a model-native tool typically has no native concept of a folder — it has elements, relationships, views, and properties, and hierarchy is not one of its primitives. That's a defensible design choice, but it creates an obligation: the hierarchy has to be preserved somewhere, or export cannot reconstruct it. In Mooodels the approach is to keep structures the canonical model has no native concept for — package hierarchy, stereotypes and specializations, diagram geometry and styling, UML attributes and operations on native EA classes, root-level tagged values — verbatim in a round-trip envelope, so that export rebuilds them rather than silently dropping them.

What you should verify is not the mechanism but the outcome. Compare the package tree in the source against whatever representation the target offers. Check the depth: if your source nests five levels and the target shows two, something collapsed. Check a leaf package with an unusual name. Then, and this is the part that actually matters, export back and look at the tree in the source tool. Preservation you can't observe on the way out isn't preservation, it's a promise.

The same reasoning applies to element nesting. Some tools let you place an element inside another element in the model tree, not just visually. If the target flattens that nesting into folder membership — which is a common and reasonable simplification — you need to know, because it changes what a containment query returns.

Check four: layout, but only if you actually depend on it

Diagram geometry is the check people either over-weight or ignore entirely, and the right answer depends on how your organisation uses diagrams. If your views are generated, filtered or auto-laid-out and nobody has ever cared exactly where a box sits, layout fidelity is close to irrelevant and you should spend the budget elsewhere. But if you have a hand-crafted landscape diagram that took two days to arrange, goes into a steering committee pack, and whose left-to-right ordering deliberately mirrors a value chain, then layout is content. Losing it is losing work.

Test it directly: open the two or three diagrams you actually care about side by side with the source. Check element positions and sizes, group and container boundaries, and whether swimlanes survived. Then check the connectors, because routing and line styling are frequently the first casualty — a manually routed orthogonal connector that avoided crossing three other lines may come back as a straight diagonal following the type default, and a dashed line that distinguished a planned relationship from an existing one may come back solid. Every element is in the right place and the diagram still says the wrong thing. Embedded images deserve a look for the same reason: logos and pasted pictures are a documented lossy boundary in most cross-tool transfers, so if a diagram's meaning depends on one, assume it will not survive.

Check five: lint immediately, before you edit anything

This is the highest-yield check on the list and the one most often left until later, when it's useless.

Run the tool's architecture rules and linting the moment the import finishes, before a single manual edit. What you're looking for is not model quality — you'll get to that — but the specific signatures of a partial import:

Do this before editing, because the lint output is only diagnostic while it's clean of your own contributions. Twenty minutes of manual work later, an orphan could be something you created, and the finding can no longer be attributed to the import. Save the first run — it's the baseline for everything after.

Check six: test the round trip deliberately, on a copy

Everything above tests one direction. The check that tests whether you can actually live in the new tool is the round trip: import, export back, re-import into the source tool, and compare.

Do this on a copy of the source repository. Not on the real one. The entire point of the exercise is to find out what goes wrong, and you want that discovery to be free.

The round-trip verification loop: import, verify, export, re-import, compare against the original Source repository Archi or Sparx EA (copy) Import source identity retained Verify counts · samples · lint Export back preserved structures rebuilt Re-import to source into the same repository Compare updated, not duplicated counts match? Element count after re-import should equal the count before the first import. Anything higher means identity was lost somewhere in the loop.
The round trip is the only test that proves identity held. Everything before it tests one direction; only the return leg shows whether objects update in place.

The question the round trip answers is whether object identity survived, and identity is the load-bearing part of any interoperability story. When Mooodels imports from Sparx EA, objects retain their source identity — the EA GUID — so a later export and re-import updates the same objects in place rather than creating new ones alongside them. Where no such identity exists in the source, matching falls back to find-or-create by name plus type, which works but is inherently less certain: rename an element in one tool and the match is gone, and you get a duplicate rather than an update.

So the pass criterion is arithmetic and brutal. After the return leg, the source repository should contain exactly the same number of elements it contained before you started. Not roughly. Exactly. If the count went up, identity was lost somewhere in the loop, and you need to know where before you trust the tool with anything that will later need to go back.

Then run one more test that people usually forget: rename an element in the new tool, export, re-import, and confirm the source shows a renamed element rather than a new one plus an abandoned original. That's the difference between a model that can genuinely live in two places and a model that can only be copied in one direction.

Check seven: read the warnings, all of them

Import warnings are the most valuable and least read artefact of the whole process. They exist precisely because the importer encountered something it could not represent faithfully and chose to tell you rather than pretend. Dismissing them converts a documented limitation into a silent surprise with a six-month fuse.

A useful import summary looks something like this:

Import complete — Enterprise Landscape (source: Sparx EA)

  Elements          1,284 read    1,284 imported
  Relationships     2,911 read    2,903 imported     8 skipped
  Views                47 read       47 imported
  Packages            136 read      136 preserved

  Warnings (3)
   [rel-to-rel]   8 relationship-to-relationship links skipped
                  (ArchiMate 3.1; not representable as a connector)
   [geometry]     12 connectors reset to type default routing
   [media]        4 embedded images on 2 views not transferred

  Identity: 1,284 of 1,284 elements carry source identity.
            0 matched by name+type fallback.

Every line there is actionable. Eight skipped relationships means eight facts that exist in your source and not in your model — go look at what they were and decide whether they mattered. Twelve reset connectors means twelve places a diagram may read differently. And the identity line is the one to read first: every object carrying source identity is the healthy case, while a significant number matched by fallback tells you how much of your round trip rests on names staying stable. Save the summary alongside the model, so that in six months "why isn't this relationship here" is a two-second lookup rather than an investigation.

The checklist

CheckHowWhat a failure looks like
Element counts by typeCompare per-type totals against the pre-import baselineTotals match but one type is short and another is over — a mapping collapsed two types into one
Relationship counts by typeSame comparison, per relationship typeA specific type is missing entirely; usually one with no target-metamodel equivalent
Documentation and propertiesLook up ten deliberately chosen elements, including the longest description and the most tagged valuesNames and types present, description fields empty across the board
Owners, lifecycle, custom fieldsCheck the specific properties your governance depends onThe field exists but is blank, or all values collapsed to a single default
Package or folder structureCompare the tree and its maximum depth; then export and inspect the tree in the source toolFive levels became two; domain packages became a flat alphabetical list
Diagram layoutOpen your two or three highest-value views side by side with the sourcePositions kept, but connector routing and dashed styling reverted to type defaults
Linting, before any editsRun rules immediately; save the output as a baselineA wave of unresolved references or a sudden population of orphans
Duplicate detectionCheck same-name, same-type pairs against the sourceLegitimate name collisions in the source became merged; or one source object became two
Round tripExport back and re-import into a copy of the source repositoryElement count rose — objects were created alongside the originals instead of updating them
Rename survivalRename one element, round-trip it, inspect the sourceA new element appears and the original is orphaned; identity was name-based
WarningsRead every line of the import summary and archive it with the modelWarnings dismissed; the same limitation resurfaces months later as a mystery

A worked example: the model that reconciled and was still wrong

Here's the shape of a failure that passes a casual check. A team imports a Sparx repository of roughly two thousand elements. The counts reconcile exactly — elements, relationships, views, all of it. The spot-checks look fine: names, types, descriptions all present. They start working.

Three weeks later, someone runs a report of applications by owning directorate and gets an empty result. The ownership was never a tagged value on the elements. It was expressed structurally, as package membership: everything under Directorate of Mobility belonged to Mobility, and that was the whole convention, understood by everyone and written down nowhere. The import preserved the hierarchy faithfully — the tree is right there, correct to five levels — but the report was written against a property that doesn't exist, because in the source it never existed either. Nothing was lost. The team simply discovered that a fact they relied on daily had no explicit representation anywhere, in either tool.

That's not an import defect; it's an import revealing something, and it's a common pattern, because migration is often the first time an organisation has to state explicitly what its conventions actually are. The checklist catches it early for a simple reason: writing down what you intend to verify forces you to articulate what the model is supposed to contain, and the gaps show up there rather than three weeks into production use.

The second half of the same story is the expensive one. Suppose that team had re-imported an updated source model a month in, before ever testing the round trip. Without retained identity they would now hold two populations of elements — some edited in the new tool, some freshly imported, matched inconsistently by name — and no clean way to tell which was which. Half a day of round-trip testing at the start prevents a week of reconciliation later.

The honest part: nothing is lossless

It's worth saying plainly, because the marketing convention in this space is to imply otherwise: no importer is lossless across arbitrarily different metamodels, and any tool claiming to be is either restricting itself to a narrow subset of both models or not telling you what it dropped.

The reason is structural, not a matter of engineering effort. Sparx EA is UML-first with an ArchiMate layer on top; Archi is ArchiMate-native; a canonical semantic model is a third thing again, deliberately simpler than either so it can serve both. Concepts that exist in one and not the others have to go somewhere: mapped to an approximation, preserved verbatim for later reconstruction, or dropped with a warning. All three are legitimate; only the last is honest by default, which is why the warnings matter so much.

Some boundaries are genuinely hard. ArchiMate 3.1 allows a relationship to connect to another relationship — a perfectly reasonable modelling construct that Sparx cannot represent as a connector at all. There is no clever workaround; something has to give, and the honest option is to skip those links and say so loudly. Element nesting flattened into folder membership is a similar trade: the containment information survives, its exact original expression does not. Embedded images and manual connector routing sit in the same category.

The goal is not a lossless import. The goal is knowing precisely what you lost, deciding whether it mattered, and being able to answer that question again in six months without re-deriving it from scratch.

That reframing changes what you should demand from a tool. Not "does it import everything" — nothing does — but: does it tell me what it couldn't take? Does it preserve what it can't natively represent, so that export can put it back? Does it keep source identity so re-import updates rather than duplicates? Can I run the round trip cheaply enough to test all of this before I commit? Those are answerable questions with observable answers, which is more than can be said for a claim of completeness.

What to do with the result

When you've worked through the checks, write the outcome down. Not a formal document — a page is plenty. What the baseline counts were, what reconciled and what didn't, which warnings you accepted and why, what the round-trip test showed, and what you know is missing. Store it next to the model.

That page stops the same investigation happening three times, and it's what you hand the next architect who asks whether the model is trustworthy — an answer with specifics instead of a shrug. If the honest answer turns out to be no, you'll know which check failed and roughly what fixing it costs, which is a far better position than vague unease about a model everyone has already started depending on.

An import that reports success is the beginning of the verification, not the end of it. An hour spent confirming what actually arrived is the cheapest insurance available on a decision you're going to be defending for years.

See the model this article describes, working in a real editor.

Try the live demo