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.
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:
- Total elements, and elements broken down by type — not just the total, because a total can reconcile while the type distribution has quietly shifted.
- Total relationships, broken down by type, with particular attention to any type you know is unusual in your model.
- Number of diagrams or views, and the number of objects on the two or three largest ones.
- Number of packages or folders, and the maximum nesting depth.
- A list of five to ten specific objects you will personally look up afterwards — chosen deliberately, not at random. More on choosing them below.
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:
- The longest description in the model. Long text finds truncation, and formatted documentation tells you whether bullets and line breaks became plain text, escaped markup, or nothing.
- An element with non-ASCII characters in its name or documentation. In any multilingual model this is routine, and accented characters, quotes and dashes are the classic casualties of a bad round trip.
- The element with the most tagged values. Tagged values are where organisation-specific meaning lives, and they're the most commonly under-tested part of any importer.
- An element with an owner or steward assigned, if your model tracks that. Ownership is often stored in a mechanism the importer treats as optional.
- Two elements with the same name but different types. If identity handling is weak anywhere, this is where it shows.
- An element with a stereotype or specialization applied.
- The most-connected element in the model — the one with twenty relationships. Check the count of its incoming and outgoing relationships specifically.
- An element that appears on five or more diagrams. Confirm it's one object referenced five times, not five objects.
- Something deeply nested in the package tree, four or five levels down.
- The most recently edited element, because it's the one most likely to use whatever feature was added to your modelling conventions last.
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:
- Unresolved references. A relationship whose source or target doesn't exist in the model is a near-certain sign that an element was dropped while its relationships were kept. This is the single clearest partial-import indicator there is.
- Orphans. Elements with no relationships at all. A few orphans are normal in most real models. A sudden population of two hundred is not — it usually means relationships failed to import while the elements succeeded, which is the mirror image of the previous case.
- Duplicates. Two elements with the same name and type. Sometimes legitimate; often the fingerprint of identity handling that fell back to name-based matching.
- Missing descriptions. If the report says ninety percent of elements have no documentation and you know the source was well documented, you've just found a field-mapping failure in one query instead of ten spot-checks.
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 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
| Check | How | What a failure looks like |
|---|---|---|
| Element counts by type | Compare per-type totals against the pre-import baseline | Totals match but one type is short and another is over — a mapping collapsed two types into one |
| Relationship counts by type | Same comparison, per relationship type | A specific type is missing entirely; usually one with no target-metamodel equivalent |
| Documentation and properties | Look up ten deliberately chosen elements, including the longest description and the most tagged values | Names and types present, description fields empty across the board |
| Owners, lifecycle, custom fields | Check the specific properties your governance depends on | The field exists but is blank, or all values collapsed to a single default |
| Package or folder structure | Compare the tree and its maximum depth; then export and inspect the tree in the source tool | Five levels became two; domain packages became a flat alphabetical list |
| Diagram layout | Open your two or three highest-value views side by side with the source | Positions kept, but connector routing and dashed styling reverted to type defaults |
| Linting, before any edits | Run rules immediately; save the output as a baseline | A wave of unresolved references or a sudden population of orphans |
| Duplicate detection | Check same-name, same-type pairs against the source | Legitimate name collisions in the source became merged; or one source object became two |
| Round trip | Export back and re-import into a copy of the source repository | Element count rose — objects were created alongside the originals instead of updating them |
| Rename survival | Rename one element, round-trip it, inspect the source | A new element appears and the original is orphaned; identity was name-based |
| Warnings | Read every line of the import summary and archive it with the model | Warnings 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