Search for Azure Cognitive Search logo

Backstage Search extension for Azure Cognitive Search Plugin

Created by AP Communications

Search extension for Azure Cognitive Search connects Backstage Search to Azure Cognitive Search. It acts as the search engine for your portal. It indexes your Backstage content into Azure, then runs queries against those indexes when users search. It fits the Backstage search architecture, so you keep the same search APIs and UI while moving the heavy lifting to Azure.

Out of the box it covers common Backstage documents like catalog entities and TechDocs. You can extend it to other document shapes by defining fields that map to Azure index schemas. The module handles creating indexes and storing documents in a way Azure accepts. It uses Azure identity for access so you can align with your existing roles. This keeps the integration simple from the app side while using Azure for relevance and scale.

This plugin is a good fit if your teams already run on Azure or want a managed search service. Use it to give one search box across your catalog and docs. Use it when you need better ranking, language analyzers, or capacity beyond in memory or database based engines. It helps standardize search without standing up a separate cluster. You keep Backstage as the front door, and let Azure AI Search do the backend work.

Installation Instructions

These instructions apply to self-hosted Backstage only.

  1. Create an Azure Cognitive Search service in your subscription.
  2. Decide which identity the Backstage backend will run as.
  3. Assign these built in roles to that identity on the search service Search Service Contributor Search Index Data Contributor
  4. The backend must authenticate with DefaultAzureCredential. Use a user identity or a service principal that has the roles above.

Install the backend module

  1. Add the package to your backend workspace.
Copy
yarn add --cwd packages/backend @platt/plugin-search-backend-module-cognitive-search

Configure Backstage

  1. Add the search settings to your app config. Set your endpoint.
Copy
# app-config.yaml
search:
  cognitiveSearch:
    endpoint: https://your-search-service-name.search.windows.net
  1. Optional set a default analyzer if you need a language specific analyzer.
Copy
# app-config.yaml
search:
  cognitiveSearch:
    endpoint: https://your-search-service-name.search.windows.net
    defaultAnalyzerName: ja.microsoft

Wire it in with the new backend system

  1. Edit packages/backend/src/index.ts. Add the module to your backend.
Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();

// keep your other modules here
backend.add(import('@backstage/plugin-app-backend/alpha'));

// add the Azure Cognitive Search module
backend.add(import('@platt/plugin-search-backend-module-cognitive-search'));

backend.start();
  1. There is no frontend change for this module. Your existing Search pages continue to work. The backend will switch to Azure Cognitive Search.

Wire it in with the old backend system

  1. Use the CognitiveSearchSearchEngine in your search backend plugin file. Replace the Lunr engine. Keep a fallback if desired.
Copy
// packages/backend/src/plugins/search.ts
import { Router } from 'express';
import {
  IndexBuilder,
  LunrSearchEngine,
} from '@backstage/plugin-search-backend-node';
import { createRouter } from '@backstage/plugin-search-backend';
import { PluginEnvironment } from '../types';
import { CognitiveSearchSearchEngine } from '@platt/plugin-search-backend-module-cognitive-search';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  const searchEngine = CognitiveSearchSearchEngine.supported(env.config)
    ? CognitiveSearchSearchEngine.fromConfig(env.config, {
        logger: env.logger,
        // optional analyzer
        defaultAnalyzerName: 'ja.microsoft',
      })
    : new LunrSearchEngine({ logger: env.logger });

  const indexBuilder = new IndexBuilder({
    logger: env.logger,
    searchEngine,
  });

  // register your collators and decorators here as usual
  // indexBuilder.addCollator(...)

  const { scheduler, taskRunner } = env;
  scheduler.scheduleTask({
    id: 'search-indexing',
    fn: async () => {
      await indexBuilder.build();
    },
    frequency: { minutes: 10 },
    timeout: { minutes: 15 },
    initialDelay: { seconds: 3 },
  });

  return await createRouter({
    engine: searchEngine,
    types: indexBuilder.getDocumentTypes(),
    permissions: env.permissions,
    config: env.config,
    logger: env.logger,
  });
}
  1. There is no frontend change for this module. Your existing Search pages continue to work. The backend will switch to Azure Cognitive Search.

Supported document types

  1. The module supports catalog entity documents.
  2. The module supports TechDocs documents.

Optional extra document types old backend system only

  1. Define extra schemas and transformers. Merge them into the engine options. This is not provided on the new backend system.
Copy
// example types
type SomeDocument1 = { /* your fields */ };
type SomeDocument2 = { /* your fields */ };

// build field definitions that match Azure Cognitive Search index fields
import {
  type CognitiveSearchIndexFields,
  type CognitiveSearchIndexTransformer,
  CognitiveSearchSearchEngine,
} from '@platt/plugin-search-backend-module-cognitive-search';

const extraSchema1: CognitiveSearchIndexFields = [
  // your field list
];

const extraSchema1Transformer: CognitiveSearchIndexTransformer<SomeDocument1> = data => {
  return {
    // map your document to indexable fields
  };
};

const extraSchema2: CognitiveSearchIndexFields = [
  // your field list
];

const extraSchema2Transformer: CognitiveSearchIndexTransformer<SomeDocument2> = data => {
  return {
    // map your document to indexable fields
  };
};

// extend the engine with extra document types
type DefaultBackstageSearchDocuments = unknown; // use your actual default union if present
type ExtendedDocumentType =
  | SomeDocument1
  | SomeDocument2
  | DefaultBackstageSearchDocuments;

function createExtendedEngine(env: PluginEnvironment) {
  return CognitiveSearchSearchEngine.fromConfig<ExtendedDocumentType>(
    env.config,
    {
      logger: env.logger,
      defaultAnalyzerName: 'ja.microsoft',
      searchIndexDefinitions: [
        {
          type: 'docType1',
          transformer: extraSchema1Transformer,
          fields: extraSchema1,
        },
        {
          type: 'docType2',
          transformer: extraSchema2Transformer,
          fields: extraSchema2,
        },
      ],
    },
  );
}
  1. Map your JSON fields to Azure index field types. Use Edm types that match your data.

Notes on authentication

  1. The backend uses DefaultAzureCredential from @azure/identity.
  2. Run the backend process in an environment where this credential can obtain a token.
  3. Make sure the identity has the Search Service Contributor and Search Index Data Contributor roles.

Set up Backstage in minutes with Roadie