What backing up Backstage means when catalog files live in Git
Teams often assume a Backstage portal is recoverable because its catalog definitions live in Git. That holds only for the descriptor files. Runtime state is not in Git, and it is what a rebuilt portal needs to behave as it did before. The answer to the question this page addresses is a list of stateful components you own, each with a backup and a restore you have tested, not a copy of the repository.
Backstage is an open source framework released under the Apache License 2.0 (SPDX: Apache-2.0), and it runs in infrastructure your organization controls. Nobody else holds its state for you. In production it uses PostgreSQL, and each backend plugin gets its own logical database through Knex, so the catalog, scaffolder task history, search index inputs, and other plugin data sit in separate databases on the same server. Use the architecture overview to confirm which plugins your deployment enables, since each one may add its own database. TechDocs output, the configuration files and secrets referenced by them, and any caches or external stores you add belong on the same inventory.
Plan a backup and restore before your first production launch, before every Backstage upgrade (where a failed bump may need a rollback), and before an audit that expects evidence of recovery. Confirm with your platform team where each piece lives, how often it is captured, who can restore it, and how long the restore takes in a rehearsal. A backup that has never been restored into a clean environment is an assumption, not a control.
Which parts of Backstage hold state you must protect
Backstage keeps most of its catalog definitions in Git, so a restore plan focuses on the state that cannot be regenerated. Each card below is one part of the installation to inventory, back up, or deliberately exclude from backups.
Plugin PostgreSQL databases
Backstage gives each backend plugin its own logical database through Knex, so the catalog, auth, scaffolder, and any search index tables that persist each live in their own schema. Back them up together with a consistent snapshot so plugins do not restore to different points in time. Confirm the exact database names and which plugins write to PostgreSQL in your deployment, since these depend on the plugins you installed.
Scaffolder task history
Scaffolder stores task records and step logs in the database, which is the only record of what a template run created, committed, or published. Losing it does not remove the repositories a template created, but it removes the audit trail teams use to answer who ran which template and with what parameters. Decide how long to keep task history and check that your backup retention covers that period.
TechDocs generated site storage
TechDocs publishes built documentation sites to a storage backend, either a cloud bucket or a local publisher directory, and the site is generated from source files in Git. The generated output is state you must protect when it is the only copy served to readers, and it can be rebuilt from source when the docs repositories are intact. Confirm which publisher your deployment uses and whether a restore includes its contents.
App-config and secrets references
The app-config files define integrations, auth providers, and database connections, while secret values usually come from environment variables or an external store. Back up the configuration repository and record which secret names exist, but never copy secret values into backup archives that have wider access than the secret store. Test that a restored environment can resolve every reference.
Catalog locations and entity providers
Catalog entities are read from descriptor files in Git and from entity providers that poll source systems, so their content is regenerated during processing after a restore. What must be preserved is the list of registered locations and provider settings, which live in configuration and the database. Treat catalog descriptors as the source of truth and confirm that every registration path is recorded in configuration.
Cache layers rebuilt, not restored
Redis, Memcached, Infinispan, or in-memory caches hold short-lived data that Backstage repopulates after startup. Restoring cache contents adds risk without benefit, so exclude them from backups and plan for a cold start after a restore. Check that the cache configuration is recorded so the restored instance points at the correct cache service.
How to set up backups and test a restore
This sequence turns a running Backstage deployment into a backup set you can restore and verify, covering the databases, storage, configuration and version records that a catalog-in-Git setup still depends on. It ends with proof that a restored instance rebuilds its catalog and shows its history.
Inventory every database and storage location
Start from the deployed app-config files and the environment variables that override them, and list every place Backstage writes state. Expect a PostgreSQL connection for the backend, plus one logical database per plugin that stores data through Knex, and any local storage used by TechDocs or search indexes. Record the host, database name, storage bucket or volume, and the owning plugin for each item, and confirm the list with the team that operates the deployment. Done means you have a single inventory document that another engineer could use to find every stateful component without reading the code.
Confirm the Git source for catalog descriptors
Catalog descriptors such as catalog-info.yaml files and any locations registered in configuration usually live in Git, so Backstage can rebuild them after a restore. Check which repositories and paths feed the catalog, whether any entities were registered through the API or a custom entity provider without a source file, and whether those registrations would be lost. Entities that exist only in the database need to be exported or moved into Git before you rely on the backup. Done means every catalog entity can be traced to a Git location or to a documented export.
Schedule consistent PostgreSQL backups for all plugin databases
Configure your PostgreSQL backup tooling so that every plugin database is captured in the same backup window, not as separate jobs that might capture different points in time. Confirm the backup covers all logical databases in your inventory, including the scaffolder and catalog databases, and that credentials for the backup job come from your secrets store. Keep the schedule and retention in your own runbook, and confirm the exact retention and point-in-time options with your database platform, since they depend on your environment. Done means a backup completes and the list of databases in the archive matches your inventory.
Back up TechDocs storage and configuration
Copy the generated TechDocs site storage, whether an object store bucket or a local publisher directory, on the same schedule as the database or on a schedule you can justify. Back up the configuration files and deployment manifests, but reference secrets by name, such as environment variable names or secret store paths, instead of copying their values into the archive. Store the backup in a location with access controls matching the rest of your Backstage data. Done means you can list the TechDocs objects in the backup and open the configuration without any plaintext credentials in it.
Record the Backstage and Node.js versions with each backup
Write the Backstage release version from the installed @backstage packages, the Node.js version used to build and run the image, and the container image digest into a manifest stored alongside each backup. Restoring onto a different Backstage or Node.js line can change schema or behavior, so the manifest tells the restore engineer which versions to start with. Check that the Node.js version is one the Backstage versioning policy currently supports for the release you run. Done means each backup set has a manifest with the three values, and a restore can be started from that manifest alone.
Restore into an isolated environment
Build a separate environment that does not send notifications, publish templates, or write to production repositories, then restore the PostgreSQL databases, TechDocs storage and configuration from the same backup set. Start Backstage using the versions recorded in the manifest and point it at restored data, using read-only or disabled integrations where possible. Keep the restore environment's network access limited to what verification requires. Done means the backend starts and reports healthy using the restored database.
Verify the catalog reprocesses after restore
Trigger or wait for catalog processing in the restored instance and confirm that entities reappear from their Git locations, with the same owners, kinds and relationships as the source instance. Compare a sample of entities and the total entity count against the production inventory, and check the processing error list for entities that fail to load. Investigate any mismatch before calling the restore successful, since missing entities often point to registrations that were never in Git. Done means the counts and sampled entities match the source, and any gaps are recorded with an owner.
Confirm scaffolder history and TechDocs are visible
Open the restored scaffolder task list and confirm that past task records appear with their status, logs and parameters, then open a TechDocs page and confirm it renders from restored storage. Check that sign-in works through the same identity provider configuration as production, since a restore that cannot resolve users is not usable. Record the results against the backup manifest so the next restore test has a baseline. Done means past tasks are listed, a documentation page renders, and sign-in succeeds, with the outcome saved in the restore log.
Restore scenarios and what each one needs
When the PostgreSQL host is lost, the databases are the primary recovery target. Backstage keeps a separate logical database for each backend plugin through Knex, so the catalog, scaffolder task history, search index state and any other plugin data all need to come back together from the same point in time. Restoring only one of them leaves plugins pointing at state that no longer matches.
- Restored: every plugin database from the same backup set, along with the database roles and connection settings the application uses.
- Rebuilt: catalog entities are repopulated from Git through the processing loop after the application starts, so entries created since the backup are recovered by reprocessing rather than from the dump.
- Rebuilt: search indexes and caches, which can be regenerated from the restored data.
- Confirm: which backup set is the consistent point in time, and whether scaffolder runs that were in progress at the failure should be cancelled or re-run.
- Confirm: that the restored Backstage version matches the version that wrote the databases, since schema changes are applied on startup.
The restore is complete only after you have checked that entities process without errors and that a sample template run succeeds against the restored state.
TechDocs stores rendered documentation output separately from the database, in the storage backend you configure. If that storage is lost but the database and catalog are intact, you do not need a full restore. The source documentation lives in each component's repository, so the rendered site can usually be regenerated instead of recovered from a copy.
- Restored: the TechDocs storage bucket or volume, only if you keep a copy of rendered sites and need them before regeneration finishes.
- Rebuilt: rendered documentation, by rerunning the TechDocs build from the source repositories that the catalog references.
- Not touched: the PostgreSQL databases and catalog entities, which remain valid.
- Confirm: which publisher mode is configured, because the recovery path differs between building locally and publishing to external storage.
- Confirm: whether any documentation sites are generated only at build time from sources you do not control, since those cannot be rebuilt from your own repositories.
After recovery, open a sample of documentation pages from different components to confirm they render and that navigation links resolve.
If entities were removed from the catalog by mistake, the usual fix is to restore the source files in Git and let the catalog reprocess them. Database restores are heavier, touch every plugin at once and roll back unrelated changes, so they should be a later option. Catalog entities are defined in descriptor files in source control, so Git history is the authoritative record of what should exist.
- Restored: the descriptor files or the location definitions that point the catalog at them, from Git history.
- Rebuilt: the entity records, through the processing loop and entity providers once the source is available again.
- Not restored: the full database, unless reprocessing cannot produce the missing entities.
- Confirm: whether the deletion came from a removed descriptor, a removed location, or a provider that stopped returning results, because each one needs a different fix.
- Confirm: whether any entities were created through the UI or API without a source file, since those have no Git copy and may need a database restore.
Verify the restored entities by checking their processing status and ownership fields, and confirm that no orphaned entities remain.
After an upgrade, you may need to restore data written by an older Backstage release into a newer one. Backstage upgrades move all @backstage packages together, and the database schema migrations run when the newer version starts. A backup taken before the upgrade is therefore a point you can return to, but the restored data must still be run through the new version's migrations, not the old ones.
- Restored: the pre-upgrade database backup and the configuration and custom code that matched that backup.
- Rebuilt: the application dependencies at the target version, using the version bump process and the upgrade helper notes for each step.
- Confirm: the exact Backstage and Node.js versions that wrote the backup, and that the target versions are supported in your release line.
- Confirm: whether any custom plugins need changes for the target version before the restored data is loaded.
- Confirm: whether a rollback to the old version is still needed, because downgrading after migrations have run is often not supported.
Test the restore in a non-production environment first, and keep the pre-upgrade backup until the upgraded system has run cleanly for a period your team agrees on.
Backup approaches and when each fits
This table compares the backup options that apply to the parts of a Backstage installation that hold state, from managed database snapshots to object storage versioning for TechDocs. Read each row for what it protects and what it leaves out, then combine options so that catalog state, plugin databases, task history and documentation are all covered. Confirm recovery time and retention figures with your database and storage vendors before relying on them.
| Approach | What it protects | What it misses | When it fits |
|---|---|---|---|
| Managed PostgreSQL snapshots | Full copies of each database instance, including every plugin database on that instance | Changes between snapshots, and per-database restores unless the platform supports them | A quick baseline for the whole instance when your managed database service offers snapshots |
| Logical dumps per database | Each plugin database separately, so one can be restored without touching the others | Point-in-time state between dumps, and consistency across databases dumped at different times | Portable copies for restore testing in a separate environment, with one dump per plugin database |
| Point-in-time recovery | Changes up to a chosen moment, which helps after a bad migration or accidental deletion | Anything outside the database, such as TechDocs files or configuration held in secrets | Teams that need to roll back to a moment just before an incident, if the database supports it |
| Object storage versioning for TechDocs | Previous versions of generated documentation objects in the bucket | Documentation sources in Git are not stored here, and deleted or expired versions depend on bucket settings | Keeping rebuilt documentation available while teams can regenerate it from source repositories |
| Git-backed catalog descriptors | Entity definitions that live in source control, such as catalog-info.yaml files | Runtime state like processing history, user sign-in data and scaffolder task records | Recovering entity definitions quickly after a catalog deletion, provided descriptors are the source of truth |
| Configuration and secrets backup | Settings files, environment-specific overrides and the secrets store references they point to | Secret values unless your secrets vault has its own backup, and anything not written down | Rebuilding the deployment on new infrastructure with the same configuration |
| Scaffolder task history export | Records of past template runs for audit and troubleshooting | Task state needed to resume an in-flight job, and outputs created in external systems | Keeping an audit trail of who created what from which template |
Protecting backups that contain sensitive data
A Backstage backup holds more than catalog data. It can contain credentials, user-entered task values, generated documentation and the sign-in configuration that decides who gets in. The cards below cover the risks to review before you schedule the first backup and again before any restore.
Secrets in exported configuration
Any token or client secret written directly into app-config.yaml or a production config file ends up in every copy of that file, including backups. Keep secrets in environment variables and reference them from configuration, so the backup holds only the variable names. Before storing a backup, search the exported configuration and database for patterns that look like tokens or keys, and confirm that your CI check blocks committed secrets.
Scaffolder history with user input
Scaffolder task records store the parameters users typed into software templates, such as project names, owners and sometimes free-text fields that people fill with hostnames, account IDs or other sensitive details. A database backup therefore carries a record of who requested what. Ask which template fields are marked as secret, decide how long task history should be kept in the backup, and restrict access to the task database to the same people who can view task logs.
Matching backup access to admin access
A backup is a full copy of the portal, so anyone who can read it can often read more than a normal user can see in the UI. Limit read access to backup buckets, snapshots and database dumps to the Backstage administrators and the operators who run restores. Log every access and review the list when someone changes roles, because a backup outlives the access that created it.
Encryption depends on the storage
Whether a backup is encrypted at rest and in transit depends on the storage you choose: an object store, a network file share, a backup appliance or a database vendor's snapshot service each have their own settings. Confirm the encryption behavior and key ownership with your storage provider before you rely on it. Verify that the transfer path from the database host to storage uses TLS and that the encryption keys are held separately from the backup files.
Sign-in resolvers on restore
A restored instance must resolve each sign-in provider to the same catalog identity it used before the restore, or users may land in new or wrong accounts. Confirm that the sign-in resolvers in configuration match the restored user entities, as the authentication guidance advises for every provider. Keep guest access off in production, and check that a restored configuration file has not re-enabled it.
Stale OAuth grants after restore
Tokens and OAuth grants issued before the incident or migration may still be valid in the identity provider even if the Backstage state that used them has changed. After a restore, revoke grants and sessions for accounts that should no longer have access, rotate client secrets that were exposed or are in doubt, and confirm the restored instance uses its current callback URLs. Record each step so the restore can be shown in a review.
Questions teams ask before backing up Backstage
How much effort does a Backstage backup and restore test take?
The effort depends mostly on how many backend plugins write to PostgreSQL, how the databases are laid out, and where TechDocs output lives. Each backend plugin gets its own logical database through Knex, so a deployment with many plugins has more databases to snapshot, restore and check. A restore test also needs a scratch environment with the same configuration, so the time spent on environment setup often matters as much as the restore itself. Ask any provider to break the estimate down by database count, storage locations and the number of environments they will exercise.
Can our own team back up and restore Backstage in-house?
Yes, if your team already runs PostgreSQL backups and has someone who knows the Backstage configuration. The work is mostly routine database and object storage operations, applied to a set of databases you must identify first. The harder part is proving that a restored instance works end to end, including sign-in, catalog processing and scaffolder history. Teams without that experience often back up the databases but never run the restore, which is the step that exposes gaps.
What access does a backup and restore engagement need from us?
A partner needs read and restore access to the PostgreSQL instance and its per-plugin databases, access to the TechDocs storage bucket or volume, read access to the Git repositories that hold catalog files, and the configuration files and secret references used by each environment. Restores into a scratch environment also need a place to run, with network reach to the identity provider and source control systems. Access should be scoped to the backup environment and recorded in your change process, and secret values should be supplied through your secret store rather than shared in tickets.
If catalog files live in Git, do we still need to back up catalog data?
Catalog descriptors that live in Git are recovered by re-ingesting them, so you do not need a separate copy of those files. However, the catalog database still holds processing state, registered locations and entities that were added through the API rather than from a repository, so those records need a database backup. Scaffolder task history, auth sessions and TechDocs output are also not recovered from Git. Confirm which entities were registered outside Git before you rely on re-ingestion alone.
How often should we test a Backstage restore?
Test often enough that a failed restore would not go unnoticed for long, and test again after any change to the database layout, plugin set or storage location. Many teams run a scripted restore on a schedule into a scratch environment and then check sign-in, catalog counts and a sample TechDocs page. A restore that has never been run is an untested backup, so the first test is usually the most valuable. Agree the frequency and the success criteria in writing before the work starts.
What changes in our backup plan after a Backstage upgrade?
An upgrade can add or rename plugin databases, change migrations, and alter which configuration keys are read. Backstage moves all @backstage packages together during upgrades, so the database schema changes can land in the same release window. Take a fresh backup before upgrading, confirm the restore procedure still matches the new plugin set, and rerun the restore test against the upgraded version. Check the Backstage versioning policy for the release line you run, since it describes which releases receive security backports.
What should a quote for backup and restore work include?
A quote should list the inventory of databases, storage locations and configuration sources in scope, the backup method for each, and the restore test steps with pass criteria. It should state which environments are covered, who runs the scheduled tests, and what evidence you receive, such as restore logs and a test record. Ask whether the work is one-time or recurring, what is handed over for your team to run, and what changes are excluded. DeployOpen agrees scope, deliverables and timelines in writing before work starts, and provides quotes from that written scope.
Official Backstage documentation to read alongside this page
Start with the Backstage architecture overview before you define your backup scope. It explains that Backstage gives each backend plugin its own logical database through Knex on PostgreSQL, which is the model your backup plan has to follow. Confirm in the overview which plugins in your deployment hold state, then list one database per plugin in your runbook, along with the scaffolder task history and any cache or search index you have decided to rebuild rather than restore. Because each database is separate, a restore can be partial, so write down which databases must be restored together to keep catalog state and task history consistent with each other.
Next, read the Backstage authentication documentation for the sign-in resolver guidance. The project advises configuring resolvers so every provider resolves to the same identity, and it advises against guest access in production. These settings live in configuration rather than in the database, so they must be captured in your Git-stored configuration and in your secrets store. Test sign-in against the restored instance before you reopen access, because a restored catalog with a mismatched resolver can produce users who cannot sign in or who map to the wrong identity.
Finally, use the keeping Backstage updated guide to check the upgrade steps that apply to a restored instance. Backups taken on one Backstage release may need the same version bump, template changes and database migrations before they run on another. Record the exact Backstage version and Node.js runtime in each backup set, and confirm with the release notes whether the restore target needs the same version or a later one. Test that path in a non-production environment, since an upgrade run during a recovery is a common source of extended downtime.
How DeployOpen scopes and delivers Backstage backup and restore
DeployOpen plans, builds and documents the backup and restore setup for a self-hosted Backstage portal inside infrastructure you control. The work covers the PostgreSQL databases, scaffolder task history, TechDocs storage and configuration, and a restore test that your team can repeat.
How we scope
- Inventory every stateful component: each plugin database, TechDocs storage, scaffolder task history and secrets references.
- Agree recovery expectations with your team in writing, including which data must return first after an incident.
- Confirm where backups are stored, who can access them and which environments the restore test will use.
How we build
- Configure scheduled backups of each PostgreSQL database and the TechDocs storage target in your own accounts or data centers.
- Document how catalog files in Git are recovered by re-ingestion, and what must be restored from outside Git.
- Run a full restore into a separate environment and record the steps, timings and any gaps found during the test.
How we hand over
- Provide a runbook covering backup schedules, retention, restore order and the commands used during a restore.
- Walk your operations team through a restore test they run themselves, with the results written down.
- Deliver configuration files, encryption and key handling notes, and a list of open items for your owners to confirm.
How we support
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.
- Ongoing support, upgrades and periodic restore testing are available as a retainer if your team wants them.
- Quotes follow from the written scope, so ask for each backup target, restore test and handover item to be listed.

