﻿---
title: Feature flags
description: Some Kibana features are gated behind feature flags or experimental configuration. Scout provides two ways to enable them: at runtime via feature flags...
url: https://www.elastic.co/elastic/docs-builder/docs/3958/extend/kibana/testing/feature-flags
products:
  - Kibana
---

# Feature flags
Some Kibana features are gated behind feature flags or experimental configuration. Scout provides two ways to enable them: **at runtime** via feature flags (without restarting the server) and **at server startup** (via custom server configurations). The table below compares the two approaches.

## When to use runtime versus server-level flags


|                        | Runtime flags                 | Custom server configs                                |
|------------------------|-------------------------------|------------------------------------------------------|
| **API**                | `apiServices.core.settings()` | `ScoutServerConfig` config set                       |
| **Restart required**   | No — applied while running    | Yes — must be present at boot                        |
| **Elastic Cloud (QA)** | Supported                     | Not supported — local only                           |
| **CI cost**            | Low — shares default servers  | Higher — dedicated server instance                   |
| **Toggle per suite**   | Yes                           | No — fixed at server start                           |
| **When to use**        | **Preferred** for most flags  | Settings required at boot (e.g., route registration) |

For custom server configs, reach out to the Apps DX team before creating one (see [below](#scout-feature-flags-custom-servers)).

## Enabling feature flags at runtime

Use `apiServices.core.settings()` to toggle feature flags while the server is running. Under the hood, this calls Kibana's [config overrides API](https://github.com/elastic/kibana/blob/main/src/core/packages/feature-flags/README.mdx#config-overrides), which forces flag values directly — bypassing the feature flag provider — so the same test code works locally and on Elastic Cloud (QA).
<note>
  Feature flag overrides are **server-wide**: they apply to the entire Kibana instance, not to a single space or worker. In [parallel suites](https://www.elastic.co/elastic/docs-builder/docs/3958/extend/kibana/testing/parallelism) all workers share the same server, so a flag set by one worker is visible to every other worker. For parallel tests, enable flags in the **[global setup hook](https://www.elastic.co/elastic/docs-builder/docs/3958/extend/kibana/testing/global-setup-hook)** so they are set once before any worker starts.The `@kbn/eslint/scout_no_core_settings_in_space_test` ESLint rule warns when `apiServices.core.settings(...)` is called inside `spaceTest` scope (directly, in `spaceTest.describe`/`beforeAll`/`afterAll`/`step`, etc.), since that scope runs in parallel across spaces sharing the same server.
</note>


### In a global setup hook (recommended for parallel suites)

Enable the flag once in `global.setup.ts` before any worker starts:
```ts
import { globalSetupHook } from '@kbn/scout';

globalSetupHook('Enable feature flags', async ({ apiServices, log }) => {
  log.info('[setup] Enabling my-feature-flag...');
  await apiServices.core.settings({
    'feature_flags.overrides': {
      'my-plugin.my-feature-flag': 'true',
    },
  });
});
```

Because feature-flag overrides are server-wide, they survive past your suite and would leak into other Scout configs sharing the same Kibana. Pair the setup with a [global teardown hook](/elastic/docs-builder/docs/3958/extend/kibana/testing/global-setup-hook#global-teardown-hook) in `global.teardown.ts` to revert the override after the suite finishes:
```ts
import { globalTeardownHook } from '@kbn/scout';

globalTeardownHook('Revert feature flags', async ({ apiServices, log }) => {
  log.info('[teardown] Reverting my-feature-flag...');
  await apiServices.core.settings({
    'feature_flags.overrides': {
      'my-plugin.my-feature-flag': false,
    },
  });
});
```


### In a test suite (sequential tests)

For sequential suites you can enable flags in `beforeAll` and reset them in `afterAll`:
```ts
import { tags } from '@kbn/scout';
import { test } from '../fixtures';

test.describe('Browse integration', { tag: tags.stateful.classic }, () => {
  test.beforeAll(async ({ apiServices }) => {
    await apiServices.core.settings({
      'xpack.fleet.experimentalFeatures': { newBrowseIntegrationUx: true },
    });
  });

  test.afterAll(async ({ apiServices }) => {
    await apiServices.core.settings({
      'xpack.fleet.experimentalFeatures': { newBrowseIntegrationUx: false },
    });
  });

  test('loads the page', async ({ pageObjects, browserAuth }) => {
    await browserAuth.loginAsPrivilegedUser();
    // ...
  });
});
```

When using `feature_flags.overrides`, the keys must match the feature flag IDs registered by the owning plugin. Overrides bypass variation and type validation, so ensure the values match what the consuming code expects.

## Custom server configs

Some settings cannot be changed at runtime and must be present when Kibana starts: plugin `enabled` flags, or anything read during the plugin `setup` lifecycle (e.g., HTTP route registration). For these cases Scout supports **custom server configuration sets** that manage a local Kibana process.
<warning>
  ⚠️ Each custom config set requires its own dedicated local server instance, which adds CI cost. **Reach out to the Apps DX team before creating one** to make sure it is the right approach for your use case. If the flag you need can be toggled at runtime, prefer the [runtime approach](#scout-feature-flags-runtime) instead — it works everywhere, including Cloud.
</warning>

The `default` config set mirrors a real Elastic Cloud deployment as closely as possible (a [Cloud-first approach](/elastic/docs-builder/docs/3958/extend/kibana/testing/scout-best-practices#design-tests-with-a-cloud-first-mindset)). Keeping it representative of the default customer experience is what lets UI and API suites from different solutions share one set of servers and run the same way locally and on Cloud, so avoid enabling a feature flag there unless it is also enabled by default on Cloud. Put non-default behavior behind a [runtime flag](#scout-feature-flags-runtime) where the flag allows it, and reach for a custom config set only when Kibana needs the setting at boot.
<tip>
  Before creating a set, check the existing sets under `config_sets/` first: if one already boots with a similar purpose (overlapping `serverArgs`), reuse it, or ask its owners whether it can be extended with a small adjustment when no existing consumer is negatively impacted. A set that duplicates another's purpose multiplies CI cost for no benefit. If you do add one, keep it minimal: import the closest existing config (usually `default`) and override only the `serverArgs` you need.
</tip>

<note>
  A custom config set is meant to be temporary. Once the setting it enables ships on by default, delete the set and move its suites back to the `default` config set.
</note>


### How custom configs work

By default, Scout starts a local server using the `default` configuration set. Custom configs live under:
```text
src/platform/packages/shared/kbn-scout/src/servers/configs/config_sets/<name>/
```

Inside that directory, create one config file per architecture + domain combination your tests target. Files follow the naming convention `<domain>.<arch>.config.ts` and must export `servers: ScoutServerConfig`.
Scout detects a custom config in two ways:
1. **Path convention**: name your test directory `test/scout_<name>/` instead of `test/scout/` and Scout automatically maps it to the `<name>` config set.
2. **Explicit flag**: pass `--serverConfigSet <name>` when starting the local server.


### Example

The `uiam_local` config set extends the default serverless config to enable UIAM authentication with a mock IdP:
```ts
import { servers as defaultConfig } from '../../default/serverless/security_complete.serverless.config';
import type { ScoutServerConfig } from '../../../../../types';

export const servers: ScoutServerConfig = {
  ...defaultConfig,
  esServerlessOptions: { uiam: true },
  kbnTestServer: {
    ...defaultConfig.kbnTestServer,
    serverArgs: [
      ...defaultConfig.kbnTestServer.serverArgs,
      '--xpack.security.uiam.enabled=true',
      '--xpack.security.uiam.url=<mock-idp-url>',
      // ... additional UIAM-specific args
    ],
  },
};
```

[Start the local server](/elastic/docs-builder/docs/3958/extend/kibana/testing/run-scout-tests#scout-run-tests-server-config-set) with the custom config:
```bash
node scripts/scout start-server --arch serverless --domain security_complete --serverConfigSet uiam_local
```