Community Edition | Enterprise Edition

SWIRL for Backstage

What it does

SWIRL for Backstage replaces the search engine behind the Backstage search plugin. Backstage keeps its collators, its search page, and its permission filtering. SWIRL supplies the index, the relevance, and results from systems that Backstage does not index.

Two things ship:

  • The npm package @swirl-search/backstage-plugin-search-backend-module-swirl, a search backend module.
  • The container image swirlai/swirl-backstage, which is SWIRL Community with an embedded Tantivy index.

The two lanes

Every query runs over two lanes and both are ranked together.

  • Indexed lane. Every document a Backstage collator produces is written to a Tantivy index inside SWIRL. Catalog entities and TechDocs pages are the usual two. Queries are answered with BM25 relevance, n-gram matching on titles, and optional typo tolerance.
  • Federated lane. SWIRL queries connected sources live, once per query. GitHub and Confluence are the sources in this release. Those results arrive under the Backstage document type swirl-federated and appear in the same result list.
SWIRL for Backstage architecture: Backstage collators and the engine module on the left, the SWIRL container with ingest API, Tantivy index, search API, and federation to GitHub and Confluence on the right A Backstage backend on the left, containing the search plugin with collators, the SWIRL engine module (indexer and query) and a permission filter. On the right, the SWIRL for Backstage container, containing an ingest API, a search API, federation, Redis, a Tantivy index on disk and a JWKS verifier. The indexer sends documents to the ingest API, the query path sends a query with the user's Backstage token to the search API and receives ranked results, and federation fans out to GitHub and Confluence. search in Backstage Backstage backend search plugin collators (catalog, TechDocs) @swirl-search engine module indexer query permission filter (AuthorizedSearchEngine) results SWIRL for Backstage container ingest API search API Redis queue and cache federation Tantivy index (on disk) JWKS verifier index documents query with the user’s Backstage token ranked results fetch public keys service account, scoped GitHub Confluence more sources Native content is indexed. External sources are searched live. One ranked list.

The engine module writes documents to SWIRL as the collators produce them, and asks SWIRL for results at query time. It forwards the Backstage plugin token unchanged, so SWIRL knows which user asked. Page 0 of a result set federates. Later pages are database reads in SWIRL, which keeps Backstage's permission paging loop cheap.

See it work

Two minutes and fifty five seconds, with narration. A stock Backstage, the same queries before and after, then GitHub results arriving in the same ranked list. Every step is on the install page. Also on YouTube: the full demo and the 30 second cut.


SWIRL for Backstage, end to end: install, the relevance difference, and the federated lane.

What it does not do

  • It does not replace collators. The catalog and TechDocs collators run on their normal schedule. Only the storage and the relevance move to SWIRL.
  • It does not index external sources. GitHub and Confluence are queried live. Nothing from them is written to the Backstage index, and SWIRL stores no copy of their content.
  • It does not change the Backstage search page. Catalog and TechDocs results render through their existing renderers. Federated results render through the default list item.
  • It does not filter federated results through Backstage permissions. Backstage can only filter what it indexed. See Security.
  • It is not a cluster. One container, one volume, no JVM, no separate database for SWIRL.

Editions

OAuth2 is the dividing line between the two editions. SWIRL Community authenticates to a federated source with one service account, shared by every portal user. SWIRL Enterprise adds sources that authenticate per user with OAuth2.

Capability Community Enterprise
Tantivy index for catalog, TechDocs, and any other collator Yes Yes
BM25 relevance, n-gram titles, typo tolerance, attribute filters Yes Yes
Federated GitHub and Confluence with a service account Yes Yes
Mandatory scope restriction on federated sources Yes Yes
Backstage permission filtering on indexed results Yes Yes
OAuth2 sources and OAuth2-only sources No Yes
Per-user identity passthrough to a federated source No Yes
Semantic cache and cross-source deduplication No Yes
License Apache 2.0, free SWIRL for Backstage SKU, licensed for use inside Backstage

In SWIRL Community every portal user sees whatever the federated source's service account can read. Read Security before you activate GitHub or Confluence.

Measured numbers

These are measurements from the first build, not targets. They were taken on 2026-09-03 on macOS on arm64.

Measurement Value
Container resident memory, idle about 2.5 GiB
Container resident memory, 5,071 documents indexed about 2.6 GiB
Image size on disk about 7 GB
Tantivy index size at 50,000 entities 34 MB
Indexing throughput at 50,000 entities about 18,600 documents per second
Mean query time at 50,000 entities, Tantivy layer 0.255 ms
Time from container start to healthy about 15 seconds
Time from Backstage backend start to the first live index 3.2 seconds

Memory and image size are dominated by the machine learning libraries SWIRL imports, not by the index. Tantivy accounts for about 150 MB. A slimmer image profile is planned. Until it ships, these are the numbers to plan against, and the Kubernetes manifest requests 768 MiB with a 2 GiB limit.

Relevance results

Nine relevance cases were run against the Backstage example catalog plus 5,000 synthetic entities, 5,071 documents in total. All nine passed on Tantivy. The same cases were run against a live Backstage using the default Lunr engine on the 71 example documents.

  • tech returns tech-radar first on Tantivy, with no team-only entity in the top five. Lunr returns 38 results and places team-a through team-d at ranks 8 to 11.
  • store returns petstore first on Tantivy. Lunr returns seven results and none of them is petstore.
  • mes returns nothing on Tantivy. Lunr returns 14 results, none containing the string, led by a person entity.
  • foo-bar.com returns the entity at rank one on Tantivy. On a catalog with no such entity Lunr returns 59 results, the first twelve of them user entities.
  • abac finds abacus, petsotre finds petstore with typo tolerance on, and attribute filters return only matching documents.

The Postgres engine was not measured in that run. Only Lunr was.

Where to go next