Harness Feature Flags lets you control releases with toggles. You can turn features on or off without a deploy. You can target specific environments or user groups. This reduces risk during rollouts. It also gives you a clean way to run experiments or handle incidents fast.
The Backstage plugin brings those flags into your portal. For each service, you can see every flag from the connected Harness project. You get the current state, the type, the environment, and recent change history. You can filter by environment to cut noise. This keeps the team focused on what matters for a given service. It removes the extra clicks of jumping between tools.
The plugin is useful in daily work. Before a release, engineers can verify the right flags are set. During a gradual rollout, the team can track status from the same place they manage the service. If something goes wrong, you can flip a kill switch fast. Product and QA get clear visibility as well. It fits into a self hosted Backstage so flags line up with the services your team owns. The result is simple visibility where you already work.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the frontend package
Run this from the root of your Backstage app
yarn add --cwd packages/app @harnessio/backstage-plugin-feature-flags
yarn install
Enable the proxy in the backend
The plugin uses the Backstage proxy. Many apps already have it enabled. If not, add it.
New backend system
Add the dependency
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
Register the proxy plugin
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';
const backend = createBackend();
backend.add(proxyPlugin());
backend.start();
Legacy backend system
Add the dependency
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
Create the proxy plugin file
// packages/backend/src/plugins/proxy.ts
import { createRouter } from '@backstage/plugin-proxy-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
});
}
Wire it up in the backend
// packages/backend/src/index.ts
import proxy from './plugins/proxy';
// inside main function where other routers are added
apiRouter.use('/proxy', await proxy(env));
Add proxy config for Harness
Add this in your app config. Put your token value for the header. Use your Harness on prem URL in target if needed.
# app-config.yaml
proxy:
'/harness':
target: 'https://app.harness.io/'
headers:
'x-api-key': '${HARNESS_API_KEY}'
You can pass the token with an env var
HARNESS_API_KEY=your_token_value yarn dev
Optional Harness base URL
Only add this if you use a custom Harness URL
# app-config.yaml
harness:
baseUrl: https://app.harness.io/
Add the Feature Flags tab to the service page
Edit the service entity page. Import the components. Add a new route so users can open the tab.
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import { EmptyState } from '@backstage/core-components';
import { Button } from '@material-ui/core';
import {
isHarnessFeatureFlagAvailable,
EntityHarnessFeatureFlagContent,
} from '@harnessio/backstage-plugin-feature-flags';
const featureFlagList = (
<EntitySwitch>
<EntitySwitch.Case if={isHarnessFeatureFlagAvailable}>
<EntityHarnessFeatureFlagContent />
</EntitySwitch.Case>
<EntitySwitch.Case>
<EmptyState
title="No Feature Flags available for this entity"
missing="info"
description="You need to add an annotation to your component if you want to enable Feature Flags for it. You can read more about annotations in Backstage by clicking the button below."
action={
<Button
variant="contained"
color="primary"
href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
>
Read more
</Button>
}
/>
</EntitySwitch.Case>
</EntitySwitch>
);
export const serviceEntityPage = (
<EntityLayout>
{/* other routes */}
<EntityLayout.Route path="/feature-flag" title="Feature Flags">
{featureFlagList}
</EntityLayout.Route>
</EntityLayout>
);
Users will see a Feature Flags tab on each service page.
Add the required entity annotation
Add the Harness project URL to the catalog info for each service that should show Feature Flags.
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
harness.io/project-url: https://app.harness.io/ng/account/<accountId>/project/<projectId>/overview
# optional
# harness.io/ci-pipelineIds: pipelineId1,pipelineId2
# harness.io/cd-serviceId: myServiceId
spec:
type: service
owner: team
lifecycle: production
That is it. The frontend reads the annotation. The backend proxy forwards requests to Harness using the token you set in the config.
Changelog
The Harness Feature Flags plugin has not seen any significant changes since a year ago.
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.