Migrating a spreadsheet or CMDB service inventory into the Backstage catalog

A service inventory in a spreadsheet or CMDB becomes Backstage catalog entities through a mapping of fields to kinds and owners, a one-off generated file or a custom entity provider, and a plan for records with no owner.

On this page

Moving a service inventory into Backstage catalog entities

Moving a spreadsheet or CMDB service inventory into Backstage is mainly field mapping, ownership cleanup and choosing a loading method, and the effort depends on data quality more than on the number of rows. Start by deciding which records become which kind of catalog entity. A row describing a deployable service usually maps to a Component, the business capability it belongs to maps to a System, and a team or person maps to a Group or User. Each mapping should be written down field by field, for example which column feeds metadata.name, spec.owner, spec.system and spec.lifecycle, and which columns have no catalog home and should be dropped or kept as annotations. Expect names that differ only in case, spaces or punctuation to collide, because catalog entity names must be unique within their kind and namespace.

The Backstage catalog is populated from descriptor files that live in source control and from entity providers that read data from elsewhere. No vendor importer exists for arbitrary spreadsheets or CMDB exports, so the loading method is designed for each source. For a one-off migration, a script can generate catalog-info files and commit them to the owning repositories, which keeps ownership in Git but depends on every service having a repository. A custom entity provider fits when the inventory must stay the system of record and sync continuously, but it is code you will maintain through upgrades. Confirm with your CMDB owner whether its export is complete and current, and check the documented provider and processor options in the Backstage software catalog documentation before choosing.

Records without an owner need a decision before loading, not after. Create a holding group or flag such entities with a clear status, and set a rule for who resolves them, because an entity with a missing or unknown owner will appear in the catalog without a team to act on it. Confirm with each team lead which orphaned records they actually run, and retire the rest rather than loading them as active. Also check that owner values refer to groups or users that exist in your identity directory, since mismatched references are a common source of broken ownership views. Agree on the cleanup deadline and the person accountable for it in writing before the first load, so the catalog does not fill with records nobody will claim.

Which inventory fields map cleanly to catalog kinds and which do not

This table compares common spreadsheet and CMDB columns with their closest Backstage catalog equivalent. Read each row as a starting point for your mapping, then confirm the kind and field names against the current descriptor format in the Backstage documentation. The main takeaway is that service, owner and dependency data usually map well, while free-text notes, non-service configuration items and owners recorded as names need a decision before import.

Inventory fieldBackstage equivalentMapping note
Service nameComponent metadata.nameMap directly, but normalize to lowercase identifiers with hyphens so names are valid entity references.
DescriptionComponent metadata.descriptionMaps cleanly; trim long pasted text to a sentence or two for readability.
Owner (team)Group referenced in spec.ownerMaps well when the team exists as a Group entity; create the Group first or the reference will not resolve.
Owner (individual name)User entity referenced by identityDoes not map directly; a person's name needs a matching User entity tied to the identity provider, so confirm the lookup key with your directory.
Lifecycle stagespec.lifecycleMaps if your values can be reduced to the lifecycle values the descriptor accepts; confirm allowed values in the docs.
System groupingSystem entity referenced in spec.systemMaps when you can name the product or domain each service belongs to; a flat list needs a grouping decision first.
Dependenciesspec.dependsOn and spec.consumesApis or providesApis relationsMaps only when dependency targets are themselves entities; free-text dependency names need to be matched or created.
Repository linkAnnotation pointing to the source locationMaps as an annotation or source reference; confirm the annotation key for your source control platform.
On-call contactLink or annotation to an external paging toolNo standard field; store as a link or annotation and confirm how your incident tool identifies the schedule.
Tagsmetadata.tagsMaps directly; keep the tag vocabulary short and consistent to stay searchable.
Free-text notesNone (no direct field)No equivalent; move notes to docs in TechDocs or to a linked page, or drop them after review.
CMDB configuration items that are not servicesResource, or no entityDoes not map to Component; servers, databases and network items need a separate kind decision or should stay in the CMDB.

One-off generated files or a custom entity provider

A spreadsheet or CMDB export can reach the Backstage catalog in two broad ways. In the first, you convert the export into catalog descriptor YAML files once, review them, and register them with the catalog like any other descriptor. Nothing runs after the load, so the catalog reflects the state of the export on the day you generated it. In the second, you write a custom entity provider, a small piece of backend code that reads the source on a schedule and creates, updates or removes entities so the catalog follows the source. The provider is the mechanism that keeps the two in step. Both approaches end with the same entity kinds and owner references, so the choice affects how changes flow, not what the catalog model looks like.

  • Generated files: a script maps export columns to Component, System, Group and User entities and writes one descriptor per record.
  • Registration: the generated files are registered through a location or repository the catalog already reads.
  • Custom provider: a backend module implements the entity provider interface and publishes its entities on a schedule.
  • Source of truth: with generated files, the export is retired after the load; with a provider, the source stays authoritative.
  • Review step: generated files can be inspected in source control before any entity appears in the portal.

Confirm with your platform team which descriptor formats and registration paths your Backstage instance already accepts before choosing an approach.

Sequence from inventory to decommissioning the spreadsheet

The sequence moves a spreadsheet or CMDB list from a reference document into a catalog that the teams use as the system of record, with a checkpoint and a sign-off at each phase. Each phase produces an artifact the next one depends on, so no phase starts until the previous output is accepted.

  1. Export and profile the source data

    Export the spreadsheet or CMDB extract to a stable file and profile it: count rows, list every column, and measure how many records are missing an owner, a name, a lifecycle status or a repository link. Duplicate names and retired services are flagged here, not fixed. The engineer doing the profiling and the inventory owner review the profile together. Done means the team agrees on the record count, the list of data-quality problems, and which records are in scope for the catalog.

  2. Define the mapping and owner rules

    Write a mapping that assigns each column to a catalog field, a kind (such as Component, System, Resource or Group) and a relationship, and decide how owners are matched to catalog User or Group entities. Set explicit rules for records without an owner, such as a placeholder owner that is visibly flagged or a holding group that the portal reports on. The platform owner and the business sponsor sign off on the mapping document. Done means every source column has a documented destination or a documented reason for exclusion.

  3. Generate or build the loader

    Choose between a one-off generated set of descriptor files committed to a catalog repository and a custom entity provider that reads the source on a schedule. Generated files suit a single cutover with a small, stable list. A provider suits a source that stays the reference for a long period. The engineer builds the chosen loader and runs it against a copy of the source. Done means a repeatable run produces the same entities from the same input, and the output validates against the descriptor schema.

  4. Pilot with one domain

    Load a single domain or team's services into a non-production Backstage instance and ask the owners to review their entities, links and relationships. Owners confirm names, lifecycles and ownership, and report any field that renders wrongly. Fixes go back into the mapping, not into hand edits of individual entities. Done means the pilot owners accept their entities and the mapping has been revised for every issue found.

  5. Run in parallel with the reference list

    Load all in-scope records and keep the spreadsheet or CMDB as the reference. A scheduled comparison reports entities missing from the catalog, catalog entities missing from the source, and ownership differences. Teams correct the reference or the mapping for each difference, and the discrepancy count is tracked until it stops changing. Done means the platform owner and inventory owner agree that remaining differences are understood and accepted.

  6. Cut over to the catalog

    Announce a cutover date in the written scope, make the catalog the system of record, and direct all new registrations, ownership changes and lifecycle updates to the catalog repository or provider. The spreadsheet becomes read-only. The sign-off comes from the inventory owner, the service owners' representative and the security or compliance lead if they rely on the list as evidence. Done means every change request is made in the catalog and the old list no longer receives edits.

  7. Retire the old list

    After a period agreed in the scope, archive the spreadsheet or CMDB export with its date and checksum, remove links to it from runbooks and onboarding material, and confirm that audit or reporting processes read from the catalog. Keep the archive available for records requests as your policies require. Done means the archive is stored, dependent processes are updated, and the owner of the inventory signs the retirement record.

Handling records without an owner

Every spreadsheet or CMDB export contains rows with no accountable team, and the catalog will either show them or hide them. The options below differ in who acts on the gap, how quickly, and whether the gap stays visible while it is open. Pick one rule before the first import so the catalog does not fill with records that look owned but are not.

Placeholder group that stays visible

Assign each ownerless record to a dedicated group, such as a team named for unowned services, so the entity still appears in the catalog with an explicit owner value. The gap is visible to anyone who browses by owner, and reports can count it. The trade-off is that the placeholder must be cleaned up, or it becomes a permanent home for abandoned services. Check that your catalog views and any ownership reports actually surface this group, and that the group has a named person who reviews it.

Triage queue for owner assignment

Route each ownerless record into a queue owned by a platform or service management team, where someone researches the service and names an owning group. This keeps ownership decisions with people who can judge them, and it gives you a backlog you can measure. The trade-off is staffing: an unstaffed queue fills quietly and the records stay in limbo. Confirm who triages, the response expectation you agree internally, and how a decision is recorded back in the source inventory.

Deprecated or excluded entities

Mark records that are retired, duplicated or out of scope as deprecated, or leave them out of the import entirely. Deprecation keeps a trace of what existed, which helps during audits of decommissioned systems. Exclusion keeps the catalog clean but removes the record from view, so no one notices if a live system was mislabeled as retired. Require a named approver for each exclusion and keep the exclusion list in your source inventory so the decision can be reversed.

Block registration until an owner is named

Reject any record without a valid owner reference during import, so nothing enters the catalog unowned. This gives the strongest guarantee that every entity has an accountable team, but it can stall the migration if many legacy records lack owners. It also means the source list must be fixed before data reaches the catalog. Test the validation on a copy of the inventory first, and agree who is notified of rejected rows and how long they can remain rejected.

What drives the effort and cost of the inventory load

This table lists the factors that change how much work a spreadsheet or CMDB import takes, whether each factor is paid once or recurs, and what to request in a written quote. Use it to see which inputs your team must gather before asking a partner for scope.

DriverWhy it changes effortOne-time or recurringWhat to ask for in a quote
Source systems and export formatsEach CMDB, spreadsheet or ticket export needs its own parser, field map and test pass, and mixed formats multiply that work.One-timeA list of every source, its format, and the mapping work assumed per source.
Data quality (duplicates, naming)Duplicate hostnames, renamed services and inconsistent casing require matching rules and manual review before entities can be trusted.One-time, with recurring cleanup if sources keep changingHow duplicates will be detected, who decides merges, and a sample review of records.
Stale or inconsistent owner dataOwners who left the company or moved teams must be confirmed before their services become catalog entities with accountable owners.One-timeWhether owner validation against the directory is in scope and how unresolved owners are reported.
Share of records without an ownerRecords with no owner need a holding decision, such as a placeholder group or a review queue, which takes time to clear.One-time at load, recurring as new orphans appearHow orphan records are flagged, held or excluded, and the process for assigning them.
Number of teams confirming ownershipEach team must verify its services, so effort grows with the count of teams and the response time of their leads.One-timeWho on the client side confirms ownership, the review cycle, and the escalation path.
One-off files versus a custom entity providerGenerated catalog files are cheaper to produce once, while a provider keeps the catalog synchronized with the source and needs ongoing maintenance.Files: one-time. Provider: build once, then recurring maintenanceWhether the choice is a one-off import or a scheduled sync, and who maintains the provider code.
Identity integration for owner resolutionMapping owner names or emails to directory users requires connecting to the identity source and handling aliases and group references.One-time setup, recurring if directory data changesThe directory system, the lookup fields used, and how group owners are represented.
Parallel runRunning the spreadsheet or CMDB alongside the catalog for a period adds reconciliation work and keeps two sources open.One-time, with a fixed end date to agreeThe length of the parallel run, the reconciliation report, and the criteria for retiring the old source.

Questions teams ask before loading a service inventory into Backstage

What does a spreadsheet or CMDB import into Backstage cost, and what drives it?

The cost depends mainly on how many record types you have, how clean the source data is, and how many owners must confirm their entries. Most of the spend is labor: someone maps each column to a catalog field, writes or reviews the generated descriptor files, and resolves records that do not fit. Tooling itself is free, since Backstage is open source under the Apache License 2.0, so you pay for people, hosting and any integration work. Ask any partner for a quote that separates one-time mapping and import work from recurring catalog maintenance, and confirm the hosting assumptions for your environment.

How long does it take to move a service inventory into the catalog?

Duration depends on the size and quality of the source list, the number of teams that must confirm ownership, and whether you generate files once or build an automated entity provider. A clean list with one owner per service moves quickly, while a CMDB with duplicate records, retired assets and unclear relationships takes longer to reconcile. Treat any duration you are given as a planning estimate tied to a written scope, and ask the provider which of the tasks in this process they have assumed and which your teams must complete.

What must our internal team provide before the import starts?

Your team needs to supply four things: a full export of the spreadsheet or CMDB with field definitions, a named owner (a team, not an individual) for each service, the source repository or location of each service, and a sign-off step where owners confirm their entries. Without confirmed owners, the import is only a list of names. Agree on who approves changes to the mapping and who can reject records before the work begins, since those decisions are the most common cause of delays.

Can our own engineers do this migration without a partner?

Yes, if you have engineers familiar with YAML, the Backstage descriptor format and your CMDB schema, and if the scope is limited to one inventory. The Backstage documentation describes the catalog descriptor format and how entities are registered, so a capable team can start there. A partner adds value when the inventory is large, spans several systems, or needs an automated provider that keeps running. Decide based on your team's capacity and skills, and confirm the details with the Backstage catalog documentation and your own data.

Does Backstage import spreadsheets directly?

Backstage does not read spreadsheets directly as a built-in feature. The catalog reads descriptor files, typically catalog-info.yaml, from source control locations or from other registered sources. To load a spreadsheet, you convert its rows into descriptor files, either once with a script or continuously through a custom entity provider that reads from your CMDB API. Confirm the current options and the entity provider interface in the Backstage software catalog documentation before you choose an approach.

How should we handle services that have no owner?

Do not assign an owner by guessing. Register records without a confirmed owner in a holding state, flag them in a report, and route each one to the team that operates the service. Catalog entities need an owner reference to appear in ownership views, so unowned records will be visible but not routable until someone claims them. Set a clear rule for how long an unowned service may remain, and decide whether it is retired, moved to a review queue or kept with a documented exception. Record every decision, since auditors and security teams will ask how ownership was established.

Will the Backstage catalog stay in sync with our CMDB during rollout?

It stays in sync only if something keeps it updated. A one-off generated file set is a snapshot, so changes made in the CMDB after the import will not appear in the catalog until you regenerate and merge the files. A custom entity provider that reads the CMDB on a schedule can keep the two aligned, but it adds a service to run and monitor. Decide which system is the source of truth for each field, state how conflicts are resolved, and plan a period where both are compared. Confirm the refresh behavior with the Backstage documentation and test it on a copy of your data.

What usually goes wrong with inventory migrations

Most inventory migrations fail in predictable ways after the import looks finished. The risks below share one root cause: the catalog becomes a copy of a source that keeps changing, or a file that holds more than it should. Each card names the check to run before the catalog is trusted.

Owners who have left

Spreadsheets often name owners by person, and those people may have moved teams or left the company. An owner value that resolves to no active user or group leaves the entity orphaned in practice, even if the import reports success. Before import, match every owner against your identity directory and list the failures. Assign each unmatched service to a team that exists, and record the decision in the review log.

Duplicate entities from overlapping sources

A service may appear in the spreadsheet, the CMDB and a Git repository with different names. Importing all three creates duplicate components that split ownership and confuse search. Choose one system of record for each field before import, and agree on a single identifier, such as the repository URL or a CMDB ID kept as an annotation. Run a duplicate check on metadata.name and on the source annotation before publishing.

Catalog drift during parallel run

Teams often keep updating the CMDB while the catalog is being validated, so the two sources diverge within weeks. Decide which source is authoritative for owners and lifecycle during the parallel run, and state it in the team's documentation. Schedule a regular diff between the generated catalog files and the CMDB export, and treat each mismatch as a defect to fix at the source, not a value to overwrite by hand.

Entity names that break references

Names taken from spreadsheet labels often contain spaces, capital letters or characters the catalog does not accept in metadata.name. Names that change later also break every dependsOn, partOf and system reference that points at them. Normalize names with a documented rule, such as lowercase with hyphens, and keep the original label in title. Validate the descriptor files in CI so an invalid name fails the build.

Secrets and internal hostnames in descriptors

Inventory exports often carry connection strings, internal hostnames, IP addresses or credentials in notes columns. Committing descriptors with these values exposes them to every reader of the catalog repository and to anyone who can view the catalog. Strip free-text columns before generation, reject known patterns in CI, and reference secrets only by name. Confirm with your security team which annotations are safe to display in the portal.

What the team must provide and receive

The client provides the inputs that make the migration possible, and the most important is a complete export of the inventory with stable identifiers for every service. Expect to supply the spreadsheet or CMDB extract in its raw form, a short data dictionary explaining what each column means in practice, and a named decision maker who signs off the mapping of fields to Backstage kinds such as Component, System, Resource and Group. Owner confirmation is the step most likely to stall, so the client should nominate people who can confirm each owner by team name or individual account. Where owners must be resolved to people, the client also needs to grant read access to the identity directory that holds users and groups, and confirm which attribute maps to the catalog user reference. Ask for an explicit list of records that will be excluded and who approved each exclusion before work starts.

The client receives artifacts it can run without DeployOpen. These include the generated descriptor files (for example catalog-info.yaml files or a set of entity definitions committed to a repository the client controls), any loader or entity provider code, the mapping documentation that records each source column, its target field and the rule applied to it, and a runbook covering how to rerun the import, how to handle new or changed records and who owns the orphan queue. The client should also receive the list of unresolved owners with the reason each one is open. Confirm in the statement of work whether the loader code is delivered under an open-source license, who holds the repository, and whether the runbook includes steps for the directory and catalog credentials, since those must be rotated and stored outside the source tree.

How DeployOpen scopes and delivers the inventory migration

DeployOpen approaches the move from a spreadsheet or CMDB export to the Backstage catalog as a scoped engagement. We agree the field mapping, the ownership rules and the generated or provider-based ingestion approach in writing before any catalog files are produced, then build, test and hand over the result inside your own infrastructure.

How we scope

  • Review a sample export to agree which records become components, APIs, systems or resources.
  • Agree the field-to-kind and field-to-owner mapping in writing before any build work starts.
  • Set the rule for records without an owner, including who triages them and by when.

How we build

  • Generate catalog descriptor files from the agreed mapping and validate them against the Backstage catalog schema.
  • Build a custom entity provider only where the source must stay live, and test its refresh behavior.
  • Run the import in a non-production Backstage instance and reconcile counts against the source list.

How we hand over

  • Deliver the mapping document, the descriptor files or provider code, and the reconciliation report.
  • Document how to correct owners, add entities and rerun ingestion without manual edits to the catalog.
  • Walk your platform and catalog owners through the handover so the process runs without DeployOpen.

How we support

  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
  • Ongoing support, upgrades and continuous testing are available as a retainer.
  • Confirm with us during scoping which post-handover support, if any, is covered by your retainer.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.