Catching up a Backstage app many releases behind: where to start
An app that has drifted for a year or more should move up through the supported release line in stages, not in one jump, and the cost of doing so depends on how much custom code and how many plugins it carries. The working method is the same one used for routine upgrades: run yarn backstage-cli versions:bump to move all @backstage packages together, then apply the template changes shown in the Backstage Upgrade Helper for each release you pass through. Whether to upgrade or rebuild comes down to how many of your packages would need rewriting along the way, which you can only learn by running the first bump against a copy of your repository.
Backstage publishes two release lines under its versioning policy. The main line ships monthly, on the Tuesday before the third Wednesday of each month, and the next line ships weekly on Tuesdays. The latest release at the time of writing is v1.55.3, published September 29, 2026, with 1.56.0 in the next line. A stale app is therefore not one or two releases behind but potentially many monthly steps, and each step may carry deprecations. Target a main line release as your destination, and check the release notes for every intermediate main line version rather than only the final one.
Before you change any version, confirm which Node.js releases your target supports. The policy supports exactly two adjacent even-numbered Node.js releases, and as of Backstage 1.46.0 these are Node.js 22 and 24. An app that has been running on an older Node.js line may need its runtime, Docker base image and CI images moved during the catch-up, not after it. Ask your team to inventory the Node.js version in use across the app, the backend, your CI pipeline and your container images, then plan the Node.js move as its own step so a runtime failure is not confused with a Backstage API change.
What changes between Backstage releases and what each change means for your app
This table compares the release mechanics, runtime support and core platform pieces that change as Backstage moves forward, and what each one means for an app that has fallen behind. Read each row as a question to answer about your own app before you pick a stepping plan. The main takeaway is that the release cadence is predictable, but the gap between your version and the current line decides how much work you face.
| Change | Impact on an old app | Action needed |
|---|---|---|
| Main release line ships monthly | Each skipped month is another set of changesets and template changes to review, so the gap grows quickly. | Record your current version and count the monthly releases since. Confirm the stepping path in the release notes. |
| Next release line ships weekly | Pinning to next builds gives you more churn than main, and an old app on next is harder to reconcile. | Confirm which line your app tracks. Move to main for the catch-up unless you have a reason to stay on next. |
| Security backports cover the last 6 months | High and critical fixes reach only recent releases where feasible, so a version older than about 6 months may miss them. | Check your version date against the policy. If it falls outside the window, treat the catch-up as a security priority. |
| Node.js 22 and 24 supported as of 1.46.0 | Versions before 1.46.0 may not match the Node.js releases your base images and CI use, and a newer Backstage may drop older Node.js. | Confirm the supported Node.js pair for your target version in the policy and align Docker images and CI with it. |
| Core built-in features: catalog, templates, TechDocs, Kubernetes, search | Descriptors, template syntax and plugin wiring for these features can change between releases, so old config may not load. | Diff your app-config and catalog files against the target version and confirm changed APIs in the release notes. |
| PostgreSQL in production with a logical database per backend plugin through Knex | Older apps may use SQLite-era assumptions or shared databases, and schema migrations run when plugins upgrade. | Confirm each plugin's database, take a backup, and plan migration runs in a staging copy before production. |
| 19 built-in authentication providers and sign-in resolver advice | Resolvers and provider config written for an old release may not map identities as expected, and guest access may still be enabled. | Review each sign-in resolver so every provider maps to one identity, and disable guest access for production. |
Choosing the upgrade path: stepping through releases or moving to a fresh app
Stepping through releases keeps your existing app, its catalog configuration, its database state and its custom code, and moves it forward one release line at a time with yarn backstage-cli versions:bump. This path fits when the app is mostly stock, the custom plugins use current APIs, and the team wants to keep history and running data intact. Each step pulls in the template changes for that release, so the work is incremental but repeated.
- Upgrade in ordered stops: Move through each release line in sequence and resolve breaking changes at each stop instead of jumping several versions at once.
- Read changesets at every stop: Each release note lists breaking changes and deprecations that affect your app and backend packages.
- Apply template changes deliberately: Use the Backstage Upgrade Helper to see what changed in the template files and merge those edits by hand.
- Check Node.js alignment: Confirm the Node.js release your target line supports, since the two supported even-numbered releases change over time.
- Keep a running test log: Record which tests, catalog ingestions and sign-in flows passed at each stop.
Before you start, inventory every package version, every local edit to files the template generated, and every plugin not published by the project. Confirm the first stop with your own environment, because the release sequence depends on where your app sits today.
Creating a fresh app means scaffolding a new Backstage app from the current template, then porting your app-config settings, custom plugins, auth resolvers and catalog data into it. This fits when the old app has drifted far from the template, local changes are spread through core files, or the team wants to retire legacy packages in the same effort. The new app starts clean, but everything you carry over must be re-tested against it.
- Start from current defaults: The new app uses the current template layout, so you avoid carrying forward stale file structures.
- Port configuration by key: Move configuration values across explicitly and test each integration, rather than copying the whole old file.
- Rewrite custom plugins against current APIs: Plugins built on removed packages need new dependencies and, often, new backend or frontend wiring.
- Migrate data and identity together: Plan how existing catalog entities, sign-in identities and any search index move into the new deployment.
- Plan a parallel run: Keep the old instance available until the new one passes your verification checklist.
Before you choose this path, list each custom plugin, its dependencies and its owner, and compare the old app's core files with the template. Ask your partner or internal team to estimate the porting effort per plugin in writing, since that figure, not the template, sets the cost of this option.
Some conditions make stepping through releases slower and riskier than starting over. The clearest signals are custom plugins written against packages that the project has removed, and undocumented edits to core files that the upgrade tooling will try to overwrite or conflict with. When several of these appear together, each release stop tends to uncover new breakage, and the team spends more time reconciling the old app than building on the new one.
- Removed packages in custom code: Plugins that still import retired packages need rewriting before any version step can succeed.
- Undocumented core-file edits: Local changes to generated files with no record of why they exist make template merges hard to review.
- No owner for custom plugins: If nobody can explain a plugin's behavior, porting it is slower and carries more risk.
- Fragile or unpinned dependencies: Packages pinned to old versions or pulled from unmaintained sources block several stops at once.
- Little test coverage: Without automated checks for catalog, sign-in and scaffolder behavior, you cannot confirm that each step preserved behavior.
If you see two or more of these signals, ask for a written comparison of both paths covering porting effort, test effort and cutover risk. Confirm the removed packages against the current release notes before you decide.
Preparation before the first version bump
A multi-release catch-up touches data, code, infrastructure and approvals at once, so the preparation work decides how safely each later step can be reversed. The cards below cover what to protect, what to record and who must agree before the first bump runs.
Full PostgreSQL backup per plugin
Backstage gives each backend plugin its own logical database through Knex, so a backup has to cover every one of them, not only the catalog. Take a consistent dump of all of them together and test a restore into a scratch instance. Record which plugin databases exist, because a catch-up can run schema migrations that cannot be reversed by rolling back code alone.
Git branch and tagged baseline
Create a dedicated upgrade branch from the commit that runs in production and tag it, so you can return to exactly what users see today. Confirm that the lock file and every @backstage package version are committed. Without a tagged baseline, the diff from a dozen releases of template changes becomes hard to separate from your own edits.
Inventory of customizations
List every local plugin, patched package, custom sign-in resolver, scaffolder action and any change made to core template files. Each item will need its own upgrade decision, and some of them may already conflict with current APIs. Mark which items depend on APIs that have since been deprecated, since those are where most catch-up effort tends to concentrate.
Production-like staging environment
Stand up a staging instance with a recent copy of production data, the same identity providers and real catalog sources. Staging should use the same PostgreSQL major version and caching backend as production. A test that only exercises the local SQLite setup will miss database, sign-in and integration failures that matter for the upgrade.
Node.js and base image dependencies
Record the Node.js version your app, CI pipeline and container base images use today. Backstage supports exactly two adjacent even-numbered Node.js releases, so confirm which pair the target release supports and whether your Docker images, native modules and build agents can move with it. Any gap here blocks the bump even when the code is ready.
Named sign-off for each step
Agree in writing who approves each stage: the staging result, the database migration, the production cutover and any rollback. Name the owners for identity, data, plugin teams and the platform team. Confirm the approval path before work starts, because a catch-up spans several releases and waiting for ad hoc decisions tends to stall it.
Upgrade sequence: stepping through releases with checks and rollback points
The sequence moves a stale Backstage app forward one controlled stop at a time, so each release has a tested build, a staging check and a rollback point before the next jump. The result is a production upgrade you can explain, reverse and repeat.
Take the baseline and backups
Record the current Backstage version from the app's @backstage packages, the Node.js version in use, the lockfile and the configuration files, then tag the commit that represents the starting point. Take a snapshot of every PostgreSQL database that backend plugins use, since each plugin keeps its own logical database. Confirm that you can restore the snapshot into a separate environment before changing any dependency. Done when the tag exists, the snapshot restores cleanly and the current build and test run are recorded as the reference.
Move the Node.js runtime into the supported pair
Backstage supports two adjacent even-numbered Node.js releases, and the versioning policy lists the pair that matches each release. Check the current Backstage version against that policy, then change the local toolchain, the Docker base image and the CI runner to a Node.js release inside the supported pair while still on your current Backstage version. Rebuild native modules and run the existing test suite on the new runtime. Done when the app builds and tests pass on the new Node.js version with no Backstage version change yet.
Bump Backstage in small steps and read each release
Run yarn backstage-cli versions:bump one release line at a time rather than jumping to the newest release in one move, and read the release notes and changesets for every release you pass. Note breaking changes, removed packages and new required configuration keys in a short upgrade log kept in the repository. Your team owns this reading step, since the changes decide which of your own code needs work. Done when the log lists each release passed, its breaking changes and the actions each one requires.
Apply template changes from the Upgrade Helper
For each stop, open the Backstage Upgrade Helper to see the changes to the app and backend templates between your current version and the target, then apply them by hand to your own app and backend packages. Pay particular attention to the backend and frontend system changes, new entry points and configuration that your app was built around. Commit template changes separately from dependency bumps so reviewers can see which lines came from the template. Done when the diff for the stop contains only the intended template edits and the app still starts locally.
Migrate custom plugins at each stop
Internal plugins usually break first because they depend on APIs that were deprecated or removed in the skipped releases. Update their package dependencies, replace deprecated imports and move them to the newer extension points where the release notes require it. Run each plugin's own tests with the new Backstage packages before combining them with the app. Done when every custom plugin builds and its tests pass against the stop's version set.
Verify sign-in resolvers map each provider to the same identity
At every stop, run sign-in with each configured identity provider in staging and confirm that the sign-in resolver returns the same catalog user for that person across providers. Check that a user who signs in with two providers ends up with one identity, and that guest access is still disabled outside test environments. Compare the resolver code with the authentication documentation after each upgrade, since resolver changes can silently create duplicate users or grant access to the wrong account. Done when a written list of test sign-ins shows one identity per person and no guest session in production configuration.
Run build, tests and a staging smoke test at each stop
Run the full build, unit tests and integration tests, then deploy the stop to staging and walk through the main portal paths: catalog browsing, a software template run, TechDocs rendering, search results and the plugins your teams use daily. Record the result and the commit hash, and tag the commit as a rollback point together with a fresh database snapshot. If any check fails, fix it on that stop before moving to the next release line. Done when the stop has a passing build, a passing smoke test, a tagged commit and a matching database snapshot.
Promote to production only after the final stop passes
Once the last stop passes staging, schedule a production window, take a final database snapshot, and deploy the tagged final commit using the same image and configuration that passed staging. Repeat the sign-in check and the smoke test in production, and keep the previous stop's image and snapshot available until the portal has run normally for a period your team agrees. If production checks fail, redeploy the last known good tag and restore the matching snapshot only when the data changes require it. Done when production passes the sign-in and smoke checks and the rollback path has been written down and tested.
Deprecations, backend and frontend system changes along the way
Across several releases, deprecated packages, changed plugin APIs and moves between legacy and newer backend or frontend system patterns surface as build failures and runtime errors, often in places the upgrade tooling does not touch. A package that was marked deprecated a year ago may now be removed, a plugin may depend on an extension point that has been replaced, and an app wired with the older backend setup may fail to start once its imports change. Expect these failures to appear in the order your build and startup checks reach them, not in the order the changes were made, so a single broken plugin can hide several separate causes.
Treat every removed or renamed API as a claim to verify, not a fact to assume. For each one, check the release notes for the exact target version and confirm the replacement package, export or extension point before editing code. The Backstage release and versioning policy explains how releases are structured, and the Upgrade Helper shows template changes between two versions, but neither replaces reading what your own code imports. Record each confirmed change in a migration log so the team can see which decisions were made against which release.
Your custom code is the largest unknown in this work. Core packages can be bumped mechanically, but internal plugins, custom backend modules, and app-level wiring were written against APIs that may have since changed, and nobody may remember which ones. Inventory every import from @backstage packages across your repositories, note which plugins use the legacy backend or frontend patterns, and estimate the rework per plugin before committing to a schedule. The inventory also tells you whether the catch-up is a series of targeted fixes or a case for rebuilding the affected parts on the current system, which is the decision the rest of this page helps you make.
What makes a catch-up longer or shorter
This table lists the factors that most change how much work a catch-up takes and how each one adds effort. Read each row as a question to answer about your own app before estimating, because most drivers compound when several apply at once. The main takeaway is that the number of release lines skipped matters less than the custom code, forks and data your app has accumulated.
| Driver | Why it adds work | How to reduce it |
|---|---|---|
| Release lines skipped | Each skipped monthly line can carry template changes, deprecations and removed APIs that must be applied in order, so the upgrade multiplies with the gap. | Step through versions in small hops using the Upgrade Helper, and confirm which release line your app should target before starting. |
| Custom plugins | Every internal plugin depends on core APIs that may have changed, and each one needs its own compatibility fixes and tests. | Inventory plugins first, retire unused ones, and drop plugins that duplicate features now in core. |
| Patched or forked @backstage packages | Local patches or forks do not receive upstream changes, so each release can conflict with them and must be reapplied or reconciled by hand. | Upstream fixes where possible, remove patches that are no longer needed, and record the rest as a list to resolve before each hop. |
| Auth providers and resolver complexity | Sign-in code written against older provider and resolver APIs must be re-verified, and identity mapping errors can lock users out or grant the wrong access. | Keep one resolver path per provider, and test sign-in for each provider in a non-production environment before cutover. |
| Node.js and base image changes | Backstage supports two adjacent even-numbered Node.js releases, so an old runtime may need several steps, and native modules and container images must change with it. | Check the current supported Node.js releases in the versioning policy, and align Docker base images and CI with the target version early. |
| Search engine changes | Elasticsearch 7 is no longer supported by Backstage search, so a search backend change means reindexing and possibly a new engine or the PostgreSQL engine. | Confirm the target search engine early, and plan reindexing as its own test step rather than an afterthought. |
| Plugins moved to community-plugins | Plugins that left the core repository use new package names and their own release cadence, so imports and versions need rewriting. | List moved plugins, check their maintenance status, and pin versions that match your Backstage release. |
| PostgreSQL data volume | Large catalog, search and plugin tables lengthen migrations and make rollback slower, and schema changes can fail on unusual data. | Take and test a backup before each migration, prune stale data, and measure migration time on a copy of production. |
| Number of environments | Each environment such as development, staging and production repeats the upgrade, config changes and smoke tests, and drift between them causes surprises. | Keep configuration in version control, promote the same build through environments, and reduce environments only where they add no test value. |
Questions teams ask before catching up a Backstage app
What does it cost to catch up a Backstage app that is many releases behind?
No fixed figure can be given before someone inspects the app, because cost follows the amount of change, not the calendar. The main drivers are how many releases were skipped, how much custom code and how many plugins sit on the old APIs, whether the app still uses deprecated packages such as backend-common, how many environments need upgrading, and how much identity and database work is involved. Fees for the inventory and for the catch-up itself are separate line items in a quote. Ask for the inventory deliverable as a fixed-scope first step, then a written estimate for the upgrade with assumptions listed. Recurring costs after the catch-up, such as monthly upgrades or retainers, should be shown separately so you can compare them with keeping the app current.
How long does a Backstage catch-up take?
No duration should be promised until the inventory is complete, because the number of breaking changes depends on the releases skipped and on your custom code. The work is shaped by the version gap, the count of custom plugins, the database and cache setup, the sign-in configuration, and how many environments must be validated. Teams that have kept a staging environment and documented their plugins usually move faster than teams that must first rediscover how the app is built. Ask the provider to state the phases, the entry and exit criteria for each, and which items depend on your staff being available for reviews and decisions.
What must our team provide for a Backstage catch-up?
The provider will need working access before estimating or starting, and most delays come from missing items rather than from the upgrade itself. Expect to provide:
- Read and write access to the Backstage app repository, plus the repositories of custom plugins and templates
- A staging environment that mirrors production, with a copy or sanitized snapshot of the PostgreSQL databases
- Test accounts in each identity provider used for sign-in, and a named contact who can approve resolver changes
- A named owner for each custom plugin who can answer questions about its behavior and approve changes
- Access to CI, container registry and the Kubernetes or hosting platform where the app runs
Confirm the list against your environment before the inventory starts.
Can our internal team catch up a Backstage app without a partner?
Yes, many teams can do it internally if they have engineers who know TypeScript, Node.js, the Backstage plugin model and their own infrastructure, and if they can give the work protected time. The hard parts are reading changelogs for every skipped release, applying template changes from the Upgrade Helper to the app and backend packages, updating custom plugins, and testing sign-in and catalog ingestion across all environments. Internal teams often underestimate the test effort and the coordination with plugin owners. A partner can be useful for the inventory, the staged upgrade plan, or specific difficult pieces, while your team keeps ownership of the code and runbook. Decide which parts you will own before comparing quotes.
When is rebuilding a Backstage app cheaper than catching up?
Rebuilding is usually cheaper when the existing app has little custom code, few plugins, or a configuration that nobody can explain, and when the catalog data can be re-ingested from source systems without loss. Catching up is usually better when the app holds custom plugins, a large catalog with history, templates in active use, or sign-in and permission settings that would take long to recreate. A useful test is to compare the inventory of what must be preserved against what a new scaffold with the current release would require. Rebuilding also has risks, including losing audit history, retraining users, and re-testing every integration, so the comparison should include those costs.
How does rollback work after a database migration in Backstage?
Rollback depends on taking a database backup before the upgrade and on knowing which plugins apply schema migrations on startup. Once a newer release has migrated the PostgreSQL schemas, running the older application code against them may fail, so a rollback usually means restoring the database backup taken immediately before the change and redeploying the previous container image. Each backend plugin uses its own logical database through Knex, so the backup plan should cover all of them together. Test the restore in staging, record the time it takes, and confirm that catalog ingestion can resume cleanly. Ask the provider to show the rollback procedure as part of the plan.
How do we get a written, fixed-scope quote for a Backstage catch-up?
Start with a short, paid or agreed inventory that produces a list of the current versions, custom plugins, deprecated packages, databases, identity providers and environments. Use that list to write the scope: the target release, the phases, the deliverables such as the upgraded repository, updated plugin code and runbook, the test evidence, and the rollback procedure. The quote should state assumptions, what your team must provide, what is excluded, and the acceptance criteria. Ask whether the work is fixed-scope with milestones, and what happens if the inventory finds more change than expected. Ask for ongoing support or upgrade retainers to be quoted separately from the one-time catch-up.
Does catching up Backstage also mean fixing security and compliance gaps?
A catch-up brings the app onto a release line that receives backported high and critical vulnerability fixes, but it does not by itself prove the app is secure or compliant. The versioning policy says high and critical issues will be backported to releases from the last 6 months where feasible, so an app many releases behind may be outside that window. Sign-in should resolve every identity provider to the same user identity, and guest access should be turned off in production. Ask for the inventory to include a review of these settings, and for the test plan to show the results. Audit assessments are carried out by independent auditors, not by the upgrade provider.
When rebuilding the app is cheaper than catching up
The choice between catching up and rebuilding should follow a written inventory of the app, not a general preference for a clean start. A rebuild from the current Backstage template gives you a supported base in one step, but you must port everything the old app did: the app-config.yaml settings, sign-in resolvers, catalog locations and processors, custom plugins, and any database or search configuration. Catching up keeps the existing history, the running state in PostgreSQL and the catalog entities already registered, and it avoids re-proving sign-in and integrations, but it means working through each intermediate release's changes in order.
Signals that favor a rebuild include: most custom code is small or already stale, the catalog data can be re-ingested from source control rather than maintained by hand, the app still uses the older backend packages across many files, and the team has little appetite to test each intermediate release. Signals that favor catching up include: the portal holds data that is hard to recreate, the sign-in setup and resolvers are intricate and already audited, several internal plugins depend on the current APIs, or the app is close to the current release line. Confirm the exact upgrade path and any deprecations for your version with the Backstage release and versioning policy and the release notes before you commit.
Write the inventory first: list each plugin, custom package, auth provider and resolver, catalog source, database and cache setting, and integration secret, and mark which ones are owned, tested and documented. Estimate the effort for both paths from that list, and ask any implementation partner to price each path against the same inventory in a written quote. Choose the path with the smaller count of items that cannot be recreated or verified, and record the decision so the next upgrade starts from a known state.
How DeployOpen scopes and delivers a Backstage catch-up
DeployOpen treats a Backstage catch-up as a fixed-scope engagement that starts with an inventory of how far the app has drifted from current releases. The work is agreed in writing, built in your own infrastructure, and handed over with documentation your team can repeat for future upgrades.
How we scope
- We inventory your app and backend packages, plugins, custom code and deprecated imports against your current Backstage version.
- The written scope states the target release, the upgrade steps, the rebuild-or-catch-up decision and the items left out.
- We confirm your Node.js version, container base images, database and CI pipeline before any version bump starts.
- Engagements are fixed-scope, and the quote follows directly from the written scope and the size of the drift found.
How we build
- We step through intermediate Backstage releases in a branch, applying template changes and recording each deprecation fixed.
- Custom plugins are moved to current extension points and tested against the target release before merge.
- Authentication, catalog ingestion and scaffolder actions are checked against your identity provider and Git platform in a staging instance.
- Test results, changed configuration keys and open risks are recorded at each step so the path can be reviewed.
How we hand over
- You receive the upgraded app, a changelog of every package and configuration change, and a list of remaining deprecations.
- A written upgrade runbook covers the version bump routine, testing steps, rollback points and owners for each area.
- We walk your engineers through the handover so they can run the next monthly release line upgrade without us.
- Open decisions, such as plugins that need a community replacement, are listed with the options and the person who must choose.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after the catch-up is complete.
- A retainer can cover monthly version bumps, security patch review and compatibility checks for custom plugins.
- Ask any provider to confirm response expectations, testing scope and who owns the change approval process in the quote.
- Your team keeps ownership of the environment, data and access, and every change stays inside your infrastructure.

