SWIRL
SWIRL for Backstage · Apache 2.0

Search for Backstage that gets the results right.

Real BM25 relevance for the catalog and TechDocs, plus GitHub and Confluence in the same list, in one compose file with no cluster and no JVM. SWIRL for Backstage is a search engine module: Backstage keeps its collators, its search page, and its permission filtering, and SWIRL supplies the index, the relevance, and the results from systems Backstage does not index.

$yarn --cwd packages/backend add @swirl-search/backstage-plugin-search-backend-module-swirl
$docker pull swirlai/swirl-backstage:0.1.1
Thirty seconds, silent: the same query answered by the stock engine and by SWIRL, then GitHub results in the same list. ▶︎ Watch the full demo (2:55)
What it does

Two lanes, ranked together.

Every query runs over both lanes and both are ranked in one list. Backstage's own collators keep running on their normal schedule; only the storage and the relevance move to SWIRL.

Backstage and SWIRL for Backstage A Backstage box connected by a pair of arrows to a SWIRL for Backstage box, with two lanes named beneath: indexed, covering catalog and TechDocs, and federated, covering GitHub and Confluence. Backstage SWIRL for Backstage indexed: catalog, TechDocs federated: GitHub, Confluence
Indexed lane

Catalog and TechDocs, with relevance that holds up.

Every document a Backstage collator produces is written to a Tantivy index inside SWIRL. Queries are answered with BM25 relevance, n-gram matching on titles, attribute filters, and optional typo tolerance. Upsert and delete by id, so there is no full rebuild and no transaction timeout on a large catalog.

Federated lane

GitHub and Confluence in the same result list.

SWIRL queries connected sources live, once per query, and nothing from them is copied or indexed. Those results arrive under the Backstage document type swirl-federated and are ranked alongside catalog and TechDocs hits. GitHub and Confluence are the two sources in this release.

Permissions

Permission-true for native content on day one.

Backstage's permission framework filters engine results per document type and per resource reference. SWIRL for Backstage passes those fields through untouched, so indexed catalog and TechDocs results are filtered exactly as they are today. Backstage can only filter what it indexed, so in SWIRL Community every federated source authenticates with one scoped service account and every portal user sees what that account can read. That is stated in the security page, and per-user authentication is the Enterprise line.

The evidence

The cases the maintainers filed, answered.

These four queries come from Backstage's own issue tracker, run against the Backstage example catalog plus 5,000 synthetic entities. The SWIRL column is Tantivy inside SWIRL for Backstage. The Lunr column is the stock Backstage engine, measured live on the 71 example documents.

QueryBackstage default engine, LunrSWIRL for Backstage, Tantivy
tech Returns 38 results and places team-a through team-d at ranks 8 to 11. This is issue 27339 reproduced on the stock engine. Returns tech-radar first, with no team-only entity anywhere in the top five.
store Returns seven results and none of them is petstore. This is issue 8835, the partial word that does not find petstore. Returns petstore first.
mes Returns 14 results, none of which contains the string, led by a person entity. Issue 27339 again: a short term pulls in entities that do not contain it. Returns nothing.
foo-bar.com On a catalog with no such entity, returns 59 results, the first twelve of them user entities. Returns the entity at rank one.

Scroll the table sideways to see every column.

The cases are drawn from the Backstage issue tracker: 27339 for tech and mes, 8835 for store and petstore, and 6177 for the partial word case, abac finding abacus, which is in the full nine case run rather than the table above. Issue 32795 is a different complaint, that the Elasticsearch engine module still targets Elasticsearch version 7, and it is not one of these relevance cases. Lunr's behaviour here is not a bug someone hid: Backstage's LunrSearchEngine adds an edit-distance-2 term and a trailing wildcard term to every query, which is the mechanism behind all three of the substring results above, and it is the same mechanism that lets Lunr find petstore from the typo petsotre with no tuning at all. Nine cases were run in total and all nine passed on Tantivy. The Postgres engine was not measured in that run. Full method, scores and reproduction steps are in the overview.

Editions

OAuth2 is the dividing line.

Everything you need to search Backstage well is in Community, under Apache 2.0, for free. SWIRL for Backstage Enterprise adds per-user authentication to federated sources and the features that depend on knowing who is asking.

CapabilityCommunitySWIRL for Backstage Enterprise
Tantivy index, BM25 relevance, n-gram titles, typo toleranceYesYes
Attribute filters and Backstage permission filtering on indexed resultsYesYes
Federated GitHub and Confluence with one service accountYesYes
Mandatory scope restriction on federated sourcesYesYes
OAuth2 sources, and sources that offer no other authenticationNoYes
Per-user identity passthrough to a federated sourceNoYes
Semantic cache and cross-source deduplicationNoYes
LicenseApache 2.0, freeSWIRL for Backstage SKU, licensed for use inside the Backstage portal

Scroll the table sideways to see every column.

The Backstage SKU is licensed for use inside the Backstage portal. A request that does not carry a verified Backstage token is refused. A full SWIRL Enterprise license removes that restriction and adds the SWIRL AI Search Assistant, which answers questions over federated results.

Request an Enterprise trial

Tell us where to send the trial license for SWIRL for Backstage Enterprise. One work email is all we need.

We reply with the license and the configuration steps. Community needs no form at all: pull the image and install the module.

What you actually run

One container, one volume, measured numbers.

SWIRL, Redis, and the Tantivy index all run inside the swirlai/swirl-backstage container against a single volume. No JVM, no cluster, and no separate database for SWIRL. On Kubernetes it is one replica, strategy Recreate, and one PersistentVolumeClaim.

Restarts

The index is on disk, so a restart is not a rebuild.

SWIRL is serving again seconds after it comes back, and it never reindexes to recover. If SWIRL is down, Backstage search returns an error rather than stale results; catalog browsing, TechDocs, and every other plugin keep working.

Memory, stated plainly

About 2.5 GiB resident today, and a slimmer build is planned.

That is the measurement from the first build, taken on 2026-09-03, not a target. It is dominated by the machine learning libraries SWIRL imports, not by the index: Tantivy accounts for about 150 MB of it. Plan against the measured number until the slimmer image profile ships.

Index and latency

34 MB on disk at 50,000 entities.

Mean query time in the Tantivy layer at that size is 0.255 ms, and indexing runs at about 18,600 documents per second. Size and speed are not the constraint here; memory is the number worth arguing about, and it is above.

One container
SWIRL, Redis, and the index, on one volume
About 30 seconds
From container start to healthy
Node 22 or 24
Backstage on the new backend system
Current plus two
Supported Backstage releases, plus anything under six months old
Questions people ask first

Three short answers.

Does this replace my collators?

No. The catalog collator, the TechDocs collator, and any other collator you run keep running unchanged, on their existing schedules and configuration. The engine module takes the documents they produce and writes them to SWIRL instead of to the previous engine. One collator is added, for the swirl-federated type, and it yields zero documents; its only job is to register the type.

Do I need Elasticsearch?

No. The index is embedded in the SWIRL process, so there is no cluster to size, upgrade, or keep alive. If you already run Elasticsearch and are happy with it, there is no urgent reason to change the indexed lane; an existing Elasticsearch index can be federated as a SWIRL source instead.

Does any data leave my network?

No, unless you configure a federated source that is outside it. The index is a directory on a volume you own, catalog and TechDocs documents travel from Backstage to SWIRL over your own network, and SWIRL Community sends no telemetry. Connecting a hosted GitHub or a Confluence Cloud site sends the query string to that vendor, which is the same traffic your engineers already generate searching those systems in a browser.

More in the Backstage FAQ, the security page, and the install guide.

Try it against your own catalog.

Community is Apache 2.0 and free. Pull the image, add the module, point it at your Backstage backend, and run the queries your engineers complain about.