Modeling domains, systems, components and resources in Backstage

Learn how to choose the depth of your Backstage catalog model, when Systems and Domains earn their place, and which relations the model generates for the catalog graph.

On this page

How to model domains, systems, components and resources in Backstage

Model enough in the Backstage catalog to show who owns each piece of software and what it depends on, and stop there. A catalog with many repositories and owners needs a structure people can navigate, but every extra layer of Domain, System and Resource entities adds descriptors to maintain and relations that can go stale. The catalog model exists so that service owners can find their components, platform teams can see shared dependencies, and auditors can trace which team owns which software and data stores.

Start from the questions the model must answer. Group components into a System when they form one user-facing capability that several teams would reason about together, and place Systems in a Domain only when your organization already has business domains that leaders recognize. Use a Resource for a database, bucket or queue that components depend on, so the dependency graph shows the shared store instead of hiding it inside one service. Each of these choices sets spec.system, spec.domain, spec.dependsOn or spec.dependencyOf fields, and the catalog generates the matching relations from them. Check the kind names, allowed fields and generated relations against the Backstage documentation for the release you run, because these details change between versions.

Revisit the model when teams reorganize, when a System has grown past what one owner can describe, or when a report that auditors ask for cannot be produced from the current graph. Before a rollout, pilot the model on one business area, review the graph with its owners, and agree in writing who maintains each level. Ask any partner quoting the work to show how the proposed model maps to your org structure, which entities will be generated by providers and which will be hand-written, and how the model will be checked when a team moves a component.

What each entity kind captures and who maintains it

Each entity kind answers a different question about your estate, so each usually has a different owner and source. Domains and Systems are typically set by architecture and product leaders, while Components and Resources are maintained by the teams that build and run them. Knowing who maintains each kind shows where the catalog data should come from.

Domain: business area

A Domain answers which business area this belongs to. It groups Systems that serve one business capability, such as payments or customer onboarding, so leaders can see ownership and risk at that level. The typical owner is a business or architecture lead who agrees the boundaries and the group accountable for them. The source is usually a curated descriptor in a central repository that changes rarely, because renaming a Domain moves everything beneath it. Check that each Domain has one accountable owner before you register Systems under it.

System: outcome boundary

A System answers which components work together to deliver one outcome. For example, a checkout flow might combine an API, a background worker and a database under one System (illustrative). The typical owner is the product or platform team that releases those components together. The source is a descriptor committed in that team's own repository, with the owner field pointing to a group from your directory. Check that a System has more than one component, or the entity probably belongs as a Component.

Component: unit teams run

A Component answers what software unit a team builds and operates. Components cover services, websites, libraries and pipelines, and they carry the annotations that link to source code, CI and monitoring tools. The typical owner is the team that commits the code and gets paged when it fails. The source is a catalog-info.yaml file stored beside the code, so the entry updates with the repository. Check the lifecycle value and owner on every Component, because ownership reports and orphan handling depend on them.

Resource: shared infrastructure

A Resource answers what shared infrastructure a component depends on, such as a database, bucket, queue or cluster. It gives the catalog a node for that infrastructure, so dependencies appear in the graph and access reviews can trace back to an owner. The typical owner is the platform or data team that provisions it, often through infrastructure-as-code. The source is usually an infrastructure repository or an inventory export, since cloud and data platforms rarely have a developer-maintained descriptor. Check that each database has one owning team, even when several components read from it.

How far to model before the catalog gets noisy

Under-modeling and over-modeling both make the catalog less useful, and they fail in opposite directions. If you register every service as a loose Component with no System above it, the catalog becomes a flat list of hundreds of entries that nobody can group by product, team or business capability. Search works, but nobody can answer "what does this payments flow depend on?" without reading each file. If you go the other way and create Domains and Systems for every grouping an architect can imagine, those parent entities start drifting. Their spec.owner values point at teams that have moved on, and their membership lists no longer match the deployed estate. A stale graph is often worse than a flat one, because readers trust it.

A practical starting test is to create a System only when a set of components shares at least one property that someone will actually maintain. Illustrative criteria to adapt, not a standard, include shared ownership (one team is accountable for every member), shared lifecycle (the components are released or retired together), and a shared deployment boundary (they live in one namespace, cluster or cloud account). Check each candidate System against two questions: can you name the owner today, and would a change to the group's membership be noticed within a sprint? If the answer to either is no, keep the components in the flat list and revisit the grouping after the next architecture review. Use spec.system on each Component only once the grouping has passed this test.

Which modeling choices fit which catalog scope

This table compares four modeling options, from plain components to Resources for stateful dependencies, against what each answers, what it costs to keep current, and the signal that a team should move to it. Read it top down: most catalogs should start at the first row and add levels only when ownership or graph navigation demands them. The main takeaway is that every added level is one more kind of entity someone must own and update.

OptionWhat it answersMaintenance cost and move-up signal
Components onlyWho owns this service, repo and on-call target?Lowest upkeep, one descriptor per deployable. Move up when owners ask which services belong together.
Components grouped into SystemsWhich components together deliver one product or user-facing capability?Each System needs an owner and a list of members kept in step. Move up when dependency views mix unrelated services.
Systems grouped into DomainsWhich business area do these Systems serve, and who answers for it at that level?Adds a small set of long-lived entities with leaders to name. Move up when leadership asks for rollups across several Systems.
Resources for stateful dependenciesWhich database, bucket or queue does a component depend on, and who runs it?Each Resource needs an owner distinct from the app team. Move up when a shared data store has no visible consumers or owner.
Relations in the graphWhat depends on what, and where does a change propagate?Relations come from descriptor fields and processors, so stale references show as broken navigation. Check them after each reorganization.
Ownership clarityDoes every entity point to a team that can change it?Ownership gaps appear first at the System and Domain level. Confirm that each owner reference resolves to a group in your org data.

How to build the model in a sequence that the catalog can check

This sequence builds the model in small, verifiable slices so each layer of relations is confirmed in the catalog before the next layer depends on it. The result is a pilot set of Systems, Components and Resources that the team trusts enough to expand.

  1. Agree entity kinds and naming rules

    The platform lead and a small group of service owners agree which kinds the model uses (Domain, System, Component, Resource, plus Group and User for ownership), how names are formed, and which lifecycle values are allowed. Write the rules down in a short standard the team can reference during reviews. This step is done when every pilot owner can state, for each kind, what it represents and what its metadata.name must look like. Names agreed here are hard to change later because relations and links point to them, so review them with the teams that will maintain the descriptors.

  2. Choose the pilot Systems from one business area

    Pick two or three Systems that serve the same business capability and have owners who will answer questions during the pilot. Keep the group small enough that one reviewer can inspect every entity by hand. Confirm with each owner which Components belong to their System and which Resources, such as databases or buckets, those Components use. The output is a written list of Systems, their Components and their Resources, with a named owner for each. If a Component could plausibly belong to two Systems, record the question and decide it before writing any descriptors.

  3. Write descriptors for the pilot set

    Teams write the catalog-info descriptors for the pilot Systems, Components and Resources in the repositories that own them, using the agreed names and the spec fields that link each entity to its System or owner. Validate each file before it is registered so syntax and required fields are caught early. The check for this step is that every pilot entity is registered and appears in the catalog with no processing errors. Anything that fails validation is fixed in the descriptor, not patched in the catalog.

  4. Confirm owners resolve

    Open each pilot System, Component and Resource and check that the owner field resolves to a Group or User entity in the catalog. An owner that appears as plain text, or that resolves to nothing, means the ownership data source or the reference is wrong and the entity will look orphaned later. Fix the reference or the org data import, then recheck. This step is complete when every pilot entity shows a resolved owner and the owning Group has the expected members.

  5. Verify the System and Component relations

    Open each pilot System and confirm it lists the Components that the descriptors say belong to it, and open each Component to confirm it points back to its System. Mismatches usually come from a misspelled system reference or a Component registered under a different namespace. Record each mismatch with the descriptor that caused it and correct it at the source. The step is done when the System-to-Component view matches the written inventory from the scoping step without exceptions.

  6. Verify Resource placement under Components

    Check that each Resource the pilot Components depend on appears under the correct Component in the relations view, and that no Resource is attached only to a System by accident. Ask the Component owners to confirm the dependencies they expect, since a missing dependency here is easy to miss in a graph view. This check confirms that impact questions, such as which Components use a given database, can be answered from the catalog. Document any Resource that is shared by several Components so the model stays consistent when more pilots are added.

  7. Review the graph and expand in controlled batches

    Walk the pilot graph with the platform team and the owners, and agree the fixes and conventions the pilot exposed, such as a naming change or a decision on where Domains fit. Update the standard, then add the next batch of Systems using the same steps. Expand only when the previous batch passes every check, so errors do not compound across the catalog. Confirm which Domain grouping the organization needs before adding Domains, because moving entities between Domains later is more work than getting the pilot right.

Which relations the model generates for the catalog graph

The catalog graph is built from references you write in the descriptors. An owner reference on a Component, a system reference that places it in a System, a dependsOn list, and providesApis or consumesApis fields each become a relation that the catalog graph and entity pages display. The model only works if those references are written deliberately, because the catalog does not infer links from names, repository layout or documentation. A Component that never declares its System, or an API that no Component lists in providesApis, simply appears with no connection, and the gap is easy to miss in a portal with hundreds of entities.

Relations depend on how each reference is written and resolved. A reference points to an entity by kind, namespace and name, so a misspelled name, a wrong namespace or a kind that does not exist in the catalog shows up as a missing link rather than an error on the owning entity. Before rollout, run a validation pass that lists every reference target and confirms it resolves to a registered entity. Treat unresolved references as defects in the descriptor, and agree on naming conventions for systems, groups and resources early so that teams do not invent variants of the same name. Confirm the exact relation names, their reverse relations (for example, how a System lists the Components that belong to it, or how a Resource shows the Components that depend on it) and which fields generate which relations in the current catalog documentation for your Backstage version. Relation names and the set of reverse relations have changed across releases, and plugins that read the graph rely on them. Write your own graph queries and dashboards against the names you confirm, and retest them when you upgrade.

How the model changes with organization shape

When one platform team owns most services, the catalog rarely needs more than a few Domains. Systems are usually added only where a group of Components is deployed and operated together, such as a shared payments stack or an internal developer tooling set. Domains and Systems often come from the platform team's own service map, written by hand in the descriptors, because no org chart maps cleanly onto the work. Approval is informal: the platform lead or a small architecture group reviews new Systems in the same pull request that adds the descriptors.

  • Start flat: Register Components with spec.owner set to the platform team, and add a System only when a second team's Components need to be grouped for search or ownership views.
  • Keep Domains optional: With one owning team, a Domain adds labels without adding decisions. Add one only when a business capability spans several Systems.
  • Source of truth: Keep the System list in the same Git repository as the platform configuration so changes travel through existing review.
  • Resources stay close to Components: Databases and buckets owned by one Component can be modeled as Resources in the same file, with dependsOn set on the Component.
  • Watch for drift: Teams that begin to own their own services will need Groups and Users from your identity source, so plan that change before the model grows.

Confirm who can approve a new System, and whether that approval happens in Git review or in a separate architecture forum.

Security and operational risks in a shared catalog model

A catalog that maps teams, systems and data stores is only as trustworthy as its ownership and visibility. The four risks below show where a model can hide accountability, expose sensitive detail or drift from what is actually running, and each one names the review or control that keeps it in check.

Unowned resources hide databases

A Resource entity for a database or bucket with no owner, or with an owner that no longer exists, means nobody is paged when it fails or receives a patch notice. Check that every Resource declares an owning Group, and run a periodic review that lists Resources without an active owner. Treat any unowned data store as an open finding until a team accepts it. This check is a process control, so confirm how your team records the review outcome.

Ownership changes without catalog updates

When a team is reorganized, a System may keep pointing at the old group because the descriptor was never edited. The result is that incidents route to people who no longer own the service. Tie catalog ownership changes to your HR or org change process, and require a descriptor update in the same change request. Ask your Backstage team to confirm how ownership data is sourced in your environment before you rely on automatic updates.

Sensitive resource details visible to all readers

Connection endpoints, account identifiers and compliance tags written into a Resource descriptor can be read by anyone who can open the catalog. Decide which attributes are safe for broad reading, keep secrets out of descriptors entirely, and point readers to the system that holds credentials. Confirm with your security team which catalog readers can see each Resource, and review the catalog read permissions against that list. Authorization configuration is a separate decision to verify in your deployment.

Drift between the model and the estate

Over time the catalog can describe a System, database or dependency that has been decommissioned, renamed or moved to another account. A model that no longer matches the running estate produces wrong impact analysis and false audit evidence. Schedule a reconciliation between catalog Resources and the cloud, Kubernetes or CMDB inventory, and record who signs off on the differences. Confirm which inventory source is authoritative for each environment before you start the comparison.

What teams ask before they model domains and systems

How much effort does a first Backstage model take?

A first model takes as much effort as the number of repositories, services and owners you need to classify, plus the time it takes to settle naming decisions. The main drivers are how many repositories hold deployable units, how many systems and domains leadership wants to see, and how many people must agree on boundaries. No supplied figure sets a duration, so ask any partner to break the effort into discovery, modeling workshops, descriptor drafting, review cycles and ingestion checks, and to tie each part to a count you have confirmed in your own environment.

What drives the cost of modeling domains and systems?

Cost follows the amount of decision-making and cleanup, not the number of YAML files. Expect more work when repositories are poorly named, when no one owns half the services, when teams disagree on what a system is, or when several reviewers must sign off on each domain. Costs are mostly one-time for the initial model, while descriptor upkeep, relation reviews and new domain decisions recur as the organization changes. When requesting a quote, ask what is counted as one unit of work and what happens when the inventory is larger than the agreed sample.

Can our internal team model domains and systems without outside help?

Yes, a capable internal team can do it, provided it has someone who knows the service landscape and someone who can make naming and boundary decisions. Teams usually struggle with the decision load, not the Backstage syntax: deciding whether a group of components is one System or two, or whether a System belongs in a Domain. An outside partner adds value by running the workshops, documenting the rules and reviewing the first descriptors, and it is fair to ask for a written scope that your team can take over afterward.

What do engineering leads and platform owners need to provide?

They need to supply decisions and knowledge, not just time. Engineering leads should confirm which services belong to their teams, which dependencies matter, and which components are retired. Platform owners should own the naming conventions, the lifecycle values, the approval path for new domains, and the decision on whether custom kinds are allowed. Ask any partner to list these participants by role in the scope, along with the number of review sessions expected from each.

How long should a pilot take to validate the model?

A pilot should be long enough to test the model against real repositories, real owners and the catalog graph, but the duration is set by scope, not by a fixed rule. Pick a bounded slice, such as one domain with a handful of systems, and check that the relations render, that ownership resolves to groups, and that teams can find their components. No supplied fact gives a pilot length, so ask the partner to propose the duration in writing and to state which checks mark it as passed.

What should a fixed-scope quote list for this work?

A fixed-scope quote should name the deliverables, the boundaries and the acceptance checks. Look for the list of repositories or inventory sources in scope, the workshops and who attends them, the descriptor types to be produced (Domain, System, Component, Resource), the relations to be generated and validated, the review cycles included, and the handover material. It should also state what is excluded, such as entity providers, custom kinds or plugin work, and what triggers a change request. Ask how acceptance is tested so you can confirm the model works in your Backstage instance before the engagement closes.

Does the model need to change when Backstage is upgraded?

The descriptor format is the part you control, and well-formed entities should carry over between upgrades, but you should confirm this against the release you run. Backstage releases follow a monthly main line and a weekly next line, so the catalog model should be reviewed as part of your upgrade routine. Plan a check of the entity kinds and relations after each upgrade, and ask any partner how they test the model against the version you intend to deploy.

What to confirm in your environment before modeling

The model you build depends on three things outside the catalog file: the entity kinds and relations your Backstage release actually supports, the identity data that feeds owners, and the people allowed to change the model. Confirm these before you decide how far to model, because each one changes what a System or Resource can reliably mean.

Supported kinds and relation names

Check which entity kinds and relation names your Backstage version ships with, and which of them your catalog rules allow. Relation names such as dependsOn, providesApi and partOf are generated from the descriptors you write, so a typo or an unsupported kind produces a graph gap rather than an error you will notice. Confirm against the documentation for the exact version you run, not a newer one, and record the answer in your modeling standard.

How your directory supplies owners

Confirm which identity directory feeds Group and User entities, how often it syncs, and whether team hierarchies are present. Every spec.owner in your model points at one of these records, so a Component owned by a group that never ingests becomes an orphan in practice. Ask whether the directory holds the team that actually runs each service, since a model with accurate Systems but stale owners still fails the people who must answer for an incident.

Where databases and buckets live

Decide whether databases, queues and buckets are registered as Resources, owned by a platform team's own catalog, or kept out of Backstage entirely. Check whether your data platform or cloud inventory already holds these records and whether a second copy would drift. A Resource only helps the graph if the component that uses it is registered with a matching relation, so confirm that the teams deploying those components will maintain both sides.

Who can change the model

Identify who may add Domains, Systems and new relations, and whether changes go through pull requests on catalog files or through an administrative path. Check your authorization setup for catalog write permissions and your review process for catalog descriptors. A model that anyone can edit will fragment within months, while one that only a central team can edit may stop reflecting how teams really ship. Agree the approval path before the first migration of entities.

How DeployOpen scopes and delivers the catalog model

DeployOpen starts every catalog modeling engagement with a written, fixed scope that names the entity kinds in use, the pilot Systems that will be modeled first, the relations the team must verify in the catalog graph, and the handover deliverables. The scope is agreed in writing before any work begins, so the boundary between modeling decisions and later expansion is visible to your architecture, platform and service owners. In practice this means listing which domains will exist, which groups of components will become Systems, which databases and buckets will be modeled as Resources, and which dependsOn, providesApis and consumesApis relations are expected to appear on each pilot System. Ask for that list to be attached to the quote so it can be checked against your own inventory.

DeployOpen implements and documents the model inside your own Backstage deployment, in your repositories and on your infrastructure. The work covers the descriptor files, the catalog rules that allow the agreed kinds, the review steps that catch misplaced entities, and a short runbook that tells your team how to add a System or Resource later. Ongoing support, upgrades and changes to the model can be handled under a retainer, which is useful once the first wave of Systems is in place and teams start registering their own components. DeployOpen does not issue audit reports, attestations or certifications. If the catalog is later used as evidence in an assessment, the independent auditor or certification body decides what it proves, and DeployOpen can prepare the records and explain how they were produced.

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.