Backstage v1.51.0: AI Models in the Catalog, OpenTelemetry Tracing, and Seven Breaking Changes

| |

7 min read

Backstage logo

Backstage just shipped v1.51.0, and it is absolutely packed.

Imagine your company has a dozen internal tools, each with its own URL, its own login, its own documentation nobody reads. Now imagine someone builds a single dashboard that glues all of them together into something your engineers actually want to use. That is Backstage — an open-source developer portal originally built at Spotify, now a CNCF incubating project adopted by companies like American Airlines, Netflix, and Epic Games. It gives your team one place to discover services, spin up new projects from templates, and manage cloud infrastructure without bouncing between forty browser tabs.

Version v1.51.0 is not a quiet maintenance bump. It lands seven breaking changes, a brand-new way to catalog AI models, a fistful of UI components, OpenTelemetry tracing support, and enough catalog performance improvements to make your database administrator weep with joy. Let us walk through the highlights.

What is New

AiResource: Your AI Models Now Live in the Catalog

If your organization is anything like everyone else’s, someone spun up an OpenAI integration last week and nobody documented it. Backstage now ships an AiResource catalog entity kind — a first-class way to register and discover AI models across your organization.

The new entity type lives in @backstage/catalog-model/alpha and can be enabled by installing @backstage/plugin-catalog-backend-module-ai-model. Alongside it, the API kind gained a spec.type: 'mcp-server' subtype with a spec.remotes list for representing MCP server connections. This means your AI models and MCP servers can now be first-class citizens in your software catalog, searchable, auditable, and hooked into your existing governance workflows.

Think of it as a phone book for every AI model your company runs — except this phone book also tells you who owns it, what it costs, and whether it is production-ready.

New UI Components: Combobox, DatePicker, and Friends

The Backstage UI library got a serious upgrade. Three brand-new components are now available:

  • Combobox — A text input paired with a filterable dropdown, supporting sectioned options, icons, sizes, and custom typed values. This is the component you reach for when a plain select does not cut it. Contributed by @jabrks in PR #34118.
  • DatePicker and DateRangePicker — Accessible date selection with calendar popovers, built on React Aria. No more hacking together a date input from random npm packages. Contributed by @Swiftwork in PR #34184.
  • Flex item propsgrow, shrink, and basis are now available on Box, Card, Grid, and Flex, making layout control much less painful. Contributed by @mtlewis in PR #33948.

The Header component also got a sticky prop that keeps the title-and-actions bar fixed at the top of its scroll container, plus new description, tags, and metadata props for richer header content. The breadcrumbs prop has been deprecated.

OpenTelemetry Tracing Arrives as Alpha

An alpha TracingService has been added to @backstage/backend-plugin-api and @backstage/backend-defaults, providing a unified interface for emitting trace spans across Backstage plugins. The service includes context and propagation support for bridging OpenTelemetry context across async boundaries.

MCP tools/call invocations now emit trace spans following OpenTelemetry server-side MCP semantic conventions, contributed by @iamEAP in PR #34087 and PR #34089. If you have been wanting to trace the full lifecycle of a scaffolder template execution or an MCP tool call through your observability stack, this is the plumbing that makes it possible.

// Example: TracingService usage (alpha)
import { coreServices } from '@backstage/backend-plugin-api';

const tracing = env.initService(coreServices.tracing);
const span = tracing.startSpan('my-operation');
// ... do work ...
span.end();

Microsoft Graph Gets Incremental Ingestion

If you are ingesting users and groups from Microsoft Graph into your Backstage catalog, the existing provider held the entire dataset in memory. For large organizations, that is, shall we say, less than ideal.

A new @backstage/plugin-catalog-backend-module-msgraph-incremental module fixes this with cursor-based incremental ingestion. Each burst processes a single page of up to 999 users or 100 groups, and the cursor is persisted so a pod restart resumes from the last completed page. Your memory footprint stays flat regardless of how many thousands of employees your HR department keeps adding. Contributed by @sriharsha9618 in PR #34053.

Catalog Performance: From Seconds to Milliseconds

The Backstage catalog backend received a battery of performance improvements that are genuinely impressive on paper:

  • Entity listing now lets PostgreSQL walk the (key, value, entity_id) index in sorted order and short-circuit on LIMIT, reducing typical paginated list times from seconds to milliseconds.
  • Entity facets use an inner join rather than WHERE entity_id IN (subquery), with measured improvements from 1.2x to 7x.
  • Missing index on relations.target_entity_ref has been added, fixing full sequential scans on orphan deletion, entity ancestry, and eager pruning queries.
  • Incremental ingestion WHERE ref IN (...) queries now use = ANY($1) with a single array parameter to reduce prepared statement bloat.
  • New migration removes duplicate rows from the search table, creates covering indices, and adds a UNIQUE constraint on (entity_id, key, value).

For large installations, the maintainers recommend running the provided SQL commands before deploying. Check the changelog for details.

Scaffolder Upgrades: Stable Form Decorators, Template Groups, and More

The scaffolder — Backstage’s template engine for bootstrapping new services — got several meaningful improvements:

  • Form decorators promoted to stable — The formDecorators field, formDecoratorsApiRef, and FormDecoratorBlueprint have moved from @alpha to @public. The previous EXPERIMENTAL_formDecorators field continues to work as a deprecated alias. Decorator input is now validated against the configured zod schema before execution.
  • Template groups — The sub-page:scaffolder/templates extension now accepts a groups config field for defining template groups on the template list page. Each group has a title and a filter predicate. Templates not matched by any group fall into an “Other Templates” group.
  • always() and failure() step functions — New status check functions for scaffolder steps. Use always() to ensure a step runs regardless of previous outcomes, and failure() to run a step only when a previous step has failed. Contributed by @Ferin79 in PR #32890.
# Template groups configuration
app:
  extensions:
    - sub-page:scaffolder/templates:
        config:
          groups:
            - title: Recommended Services
              filter:
                spec.type: service
            - title: Documentation
              filter:
                spec.type: documentation

Breaking Changes You Need to Know About

This release carries seven breaking changes. Here is what you need to address during upgrade:

  • NavItemBlueprint removed — Navigation items are now discovered from PageBlueprint extensions based on their title and icon params. Set title and icon on the page extension instead.
  • PortableSchema.schema property form removed — The schema member is now a plain method. Use schema() instead of direct property access like schema.type.
  • OIDC default patterns hardened — The permissive ['*'] wildcards for CIMD and DCR have been replaced with specific defaults for known MCP clients. If you have custom MCP clients, add their patterns to the allow list.
  • PolicyQueryUser type cleaned up — The token and expiresInSeconds fields have been removed. A new CachedUserInfoService with a 5-second TTL cache and in-flight request coalescing has been added.
  • Catalog pagination excludes entities without sort field — Entities lacking the order field are now excluded from results and totalItems count.
  • Microsoft Graph filters disabled users by default — The provider automatically applies accountEnabled eq true. If you need disabled accounts, set the filter explicitly. Contributed by @mtlewis in PR #34165.
  • Backstage UI breaking changes — Removed the main header class from the Header component. @remixicon/react limited to versions below 4.9.0 due to a license change. React Aria updated to v1.17.0 and migrated to monopackages.

Also Worth Mentioning

  • ExtensionPointFactoryMiddleware — A new middleware type for replacing extension point outputs at backend creation time. Contributed by @UsainBloot in PR #33782.
  • AWS web identity token file support — Added webIdentityTokenFile to @backstage/integration-aws-node for AssumeRoleWithWebIdentity credential chains. Contributed by @hudsonb in PR #34149.
  • TechDocs air-gapped font control — Disable external font downloads with techdocs.generator.mkdocs.disableExternalFonts for air-gapped instances. Contributed by @karthikjeeyar in PR #31838.
  • Experimental BUI scaffolder form theme — Enable Backstage UI variants for all default scaffolder field extensions with enableBackstageUi: true.
  • Deprecated immediate mode stitching — The catalog.stitchingStrategy.mode: 'immediate' setting now logs a warning. Immediate mode will be removed in the next release.

Bug Fixes

Among the 30-plus fixes, a few stand out:

  • Fixed scheduler sleep overflow — Durations longer than ~24.8 days would fire immediately due to Node.js setTimeout overflowing its 32-bit millisecond limit.
  • Fixed entity page sub-path routing — Unknown sub-paths on entity pages no longer silently render the first available route.
  • Fixed Valkey cluster mode — Now uses the correct Cluster class instead of createCluster. Contributed by @ganievs in PR #33895.
  • Fixed widget editing on home page — Widgets are now movable and resizable after saved edits. Contributed by @aurnik in PR #33721.
  • Fixed disabled nav items appearing in navigation bar. Contributed by @benjidotsh in PR #33788.
  • Fixed race condition in CachedUserInfoService — A failed request could incorrectly evict a newer cache entry.
  • Invalid feature flag declarations no longer crash the app during bootstrap — they are reported through the error collector and skipped.

There are no security fixes in this release.

Big shoutout to all 34 contributors who made this release happen.

Learn More