<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Kibana - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Kibana - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/search-labs/blog/category/kibana</link>
    </image>
    <link>https://www.elastic.co/search-labs/blog/category/kibana</link>
    <atom:link href="https://www.elastic.co/search-labs/rss/category/kibana.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[en]]></language>
    <lastBuildDate>Sat, 12 Sep 2026 00:30:12 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Dashboard activity logs: Find out which Kibana dashboards get used]]></title>
    <description><![CDATA[Kibana now logs who viewed, edited or deleted each dashboard, how long it took and what failed, so you can catch a broken dashboard before anyone reports it.]]></description>
    <content:encoded><![CDATA[<p>Kibana logs every dashboard view, edit, create, delete, and refresh, along with the user behind each one. Two lines in <code>kibana.yml</code> enable this logging. When you point Discover at the index, you can find the dashboards that nobody opened in 30 days and rank them by load time or see who edited the one that broke this morning. Dashboard <a href="https://www.elastic.co/docs/reference/kibana/user-activity">activity logs</a> run on self-managed clusters today, with Elastic Cloud support coming.</p><h2>How dashboard activity logs differ from the Kibana audit log</h2><p>Dashboard activity logs and the <a href="https://www.elastic.co/docs/reference/kibana/kibana-audit-events">Kibana audit log</a> both write structured logs about user actions, but they answer different questions.</p><p>
</p><p><strong>Kibana audit log</strong></p><p><strong>Dashboard activity logs</strong></p><p>Answers</p><p>Who accessed what, and when</p><p>Which dashboards are used, and how well they perform</p><p>Built for</p><p>Security and compliance teams</p><p>Kibana admins and dashboard owners</p><p>Tracks</p><p>Security-relevant events across Kibana</p><p>Five dashboard actions: create, update, delete, view, refresh</p><p>Enabled by</p><p>Its own setting in <code>kibana.yml</code></p><p><code>user_activity.enabled: true</code> in <code>kibana.yml</code></p><h2>What dashboard activity logs capture</h2><p>The user activity service records structured events every time a user interacts with a dashboard. Each event captures <em>what happened</em> and <em>to which dashboard</em>, in addition to <em>who did it</em>. Five actions are tracked:</p><p><strong>Action</strong></p><p><strong>Fires when</strong></p><p><strong>Includes duration</strong></p><p><code>dashboard_create</code></p><p>A dashboard is created</p><p>No</p><p><code>dashboard_update</code></p><p>An edit is saved</p><p>No</p><p><code>dashboard_delete</code></p><p>A dashboard is removed</p><p>No</p><p><code>dashboard_view</code></p><p>A user opens a dashboard</p><p>Yes, time on the dashboard until they navigate away</p><p><code>dashboard_refresh</code></p><p>A user changes filters or time range, or auto-refresh runs</p><p>Yes, refresh duration</p><p>Very often, a <code>dashboard_view</code> event also triggers a refresh.</p><p>Every event carries the same core fields, with two that appear conditionally:</p><p><strong>Field</strong></p><p><strong>What it holds</strong></p><p><strong>Present on</strong></p><p><code>user.name</code></p><p>Name of the user who performed the action</p><p>Every event</p><p><code>user.email</code></p><p>Email address of the user</p><p>Every event</p><p><code>user.roles</code></p><p>Roles assigned to the user</p><p>Every event</p><p><code>object.name</code></p><p>Dashboard name</p><p>Every event</p><p><code>object.id</code></p><p>Dashboard ID</p><p>Every event</p><p><code>kibana.space</code></p><p>Kibana space the dashboard belongs to</p><p>Every event</p><p><code>client.ip</code></p><p>IP address the request came from</p><p>Every event</p><p><code>event.action</code></p><p>Which of the five actions occurred</p><p>Every event</p><p><code>event.outcome</code></p><p>Whether the action succeeded or failed</p><p>Every event</p><p><code>event.duration</code></p><p>Time taken, in nanoseconds</p><p><code>dashboard_view</code> and <code>dashboard_refresh</code></p><p><code>error.type</code> / <code>error.message</code></p><p>Error class and message when something fails</p><p>Events where <code>event.outcome</code> is <code>failure</code></p><h2>How Kibana records dashboard activity</h2><p>Under the hood, Kibana plugins report events from the browser or server through a core client, and valid events are written to a dedicated logger. No data is sent to a third party; because events are standard JSON logs, you control where they go and how they’re ingested.</p><h2>What you can do with dashboard usage data</h2><p>Dashboard activity data answers five operational questions that would otherwise require further investigation:</p><ul><li><p><strong>Clean up unused dashboards.</strong> Filter for dashboards with zero <code>dashboard_view</code> events. If nobody's looking at it, archive it. This is critical for customers who are managing thousands of dashboards. </p></li><li><p><strong>Troubleshoot performance.</strong> The <code>event.duration</code> field tells you exactly how long each dashboard load or refresh takes. Sort by duration to find your slowest dashboards.</p></li><li><p><strong>Edit history.</strong> Every create, update, and delete is logged with the user who made the change. You no longer have to wonder who modified a critical dashboard or when it happened.</p></li><li><p><strong>Plan capacity.</strong> Identify users running heavyweight queries during peak hours. If one user's auto-refresh is hammering the cluster every 10 seconds, you'll see it.</p></li><li><p><strong>Monitor errors proactively.</strong> Dashboards throwing errors surface immediately through <code>error.type</code> and <code>error.message</code> fields, so you don’t need to wait for users to report them.</p></li></ul><h2>How to enable dashboard activity logs in Kibana</h2><p>Add two lines to your <code>kibana.yml</code> ( the service is disabled by default):</p>user_activity:
  enabled: true<p>Events will start flowing immediately using a default JSON console appender. You can customize the output appender and filter specific actions using the same logging configuration schema that Kibana already uses:</p>user_activity:
  enabled: true
  appenders:
    console_json_default_appender:
      type: console
      layout:
        type: json
  filters:
    - policy: keep
      actions: [dashboard_view, dashboard_refresh]<p>Ship these logs into an Elasticsearch index (for example, via Filebeat), and you have a fully queryable dataset of dashboard usage.</p><h2>How to query dashboard activity in Discover</h2><p>Once your activity logs are indexed, open Discover and point it at your user activity index pattern. You'll immediately see every dashboard interaction as a structured event, and they’re filterable by action type, user, dashboard name, and time range.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4c49281e39a0301e/6a950fc6a3077ca19c3fe663/1.png" alt="Kibana Discover showing dashboard activity logs with event.action, object.name, duration and outcome columns" /><p>From here, you can quickly answer specific questions like the examples below. </p><h3>How many times was a dashboard viewed? </h3><p>Type your question in natural language in the Discover query editor, and press <strong>Cmd+J</strong> to automatically generate the Elasticsearch Query Language (ES|QL) query, as shown below:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt68dce42018ead590/6a9510d5a16336aae0371701/2.gif" alt="Generating an ES|QL query from plain language in Discover to search dashboard activity logs" /><h3>Which dashboards had zero views in the last 30 days?</h3><p>Dashboards with no activity simply don't appear in the logs, so you can't filter directly for zero views. Instead, this query works backward, pulling every dashboard created (and not deleted) in the past year and then checking which of those had zero views in the last 30 days.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5fe21fc80d3e276/6a9510f5923082d373c4a4f0/3.png" alt="ES|QL query on dashboard activity logs listing 30 Kibana dashboards with zero views in the last 30 days" /><h3>Which dashboards took longer than 10 seconds to load?</h3><p>Note that <code>event.duration</code> is recorded in nanoseconds, so the query converts to seconds before filtering:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaa956eb37e5278e8/6a95113b6fe1457f2bb1bf89/4.png" alt="ES|QL query ranking slow Kibana dashboards by load time, topped by Host Metrics Overview at 69 seconds" /><h3>Which dashboards are throwing errors, and what's failing?</h3><p>This query shows dashboards with one or more panels throwing errors during <code>dashboard_refresh</code> events, so you can quickly spot recurring issues and prioritize fixes:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8911faf07ccd694f/6a951153ecbe18f7691e19c0/5.png" alt="Dashboard activity logs showing failed dashboard refreshes grouped by error, with 17 errors on one dashboard" /><h2>Build a dashboard usage overview with AI chat</h2><p>We’re planning to add out-of-the-box dashboards along with the activity logs, but in the meantime, instead of manually building visualizations, open the <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/chat">AI chat</a> in Kibana and ask it to create a dashboard from your user activity data. </p><p>The generated dashboard gives you at-a-glance visibility into your most-viewed dashboards, heaviest users, slowest-performing panels, and recent errors; that is, exactly the operational view that large deployments need.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0734798e18f535af/6a9511928814aa03da89c1be/6.gif" alt="Building a dashboard usage overview from the user-activity-logs index using Agent Chat in Kibana" /><h2>Get started with dashboard activity logs</h2><p>User activity logs are available in Kibana 9.5. Begin by enabling the service. Then ship the logs into an index, and start building the operational visibility that your team has been asking for. For full configuration details and the complete event schema, see the <a href="https://www.elastic.co/docs/reference/kibana/user-activity">user activity documentation</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/dashboard-activity-logs-kibana</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/dashboard-activity-logs-kibana</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[Operations]]></category>
    <category><![CDATA[Analytics]]></category>
    <dc:creator><![CDATA[Teresa Alvarez Soler,Rudolf Meijering]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt505cee76dae8eff8/6a950f70e657a3cdea75aeb7/image4.png" length="0" type="image/png"/>
    <pubDate>Mon, 31 Aug 2026 15:15:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Migrating 1,100 files to Redux Toolkit v2 without freezing the Kibana monorepo]]></title>
    <description><![CDATA[Kibana gave Redux Toolkit v2 the default package name and pushed v1 onto an explicit alias, which inverts the usual migration order. Webpack externals, yarn resolutions and an ESLint rule keep React Redux v7 and v9 out of each other's way.]]></description>
    <content:encoded><![CDATA[<p>We moved roughly 1,100 files in the Kibana monorepo onto <a href="https://github.com/elastic/kibana/pull/235577">Redux Toolkit (RTK) v2</a> aliases without asking a single plugin team to pause feature work. The usual migration pattern runs the other way around. Default package names (<code>@reduxjs/toolkit</code>, <code>react-redux</code>, <code>redux</code>) now resolve to v2, and existing v1 code sits behind explicit aliases, like <code>redux-toolkit-v1</code> and <code>react-redux-v7</code>. Both versions live in <code>node_modules</code> at once, kept apart at runtime by npm aliases and webpack module replacement. An ESLint rule scoped to 36 plugin paths catches anything that tries to cross. When a team is ready, it deletes its path from that list and switches back to the default imports, and the teams around it carry on shipping.</p><h2>Why upgrade to Redux Toolkit v2?</h2><p>RTK v2 was released in late 2023. That's nearly three years of running on a major version behind in one of the most widely used state management libraries in the JavaScript ecosystem. It reflects how hard this upgrade is in a codebase of Kibana's size. A <a href="https://github.com/elastic/kibana/pull/178986">previous attempt</a> tried the big-bang approach and stalled when the real scope became clearer. </p><p>So what does v2 actually bring? It ships alongside Redux core 5.0, React-Redux 9.0, Reselect 5.0, and Redux Thunk 3.0. React-Redux 9.0 requires React 18 and drops the <code>useSyncExternalStore</code> shim that v8 carried for React 16/17. Since Kibana already runs React 18, upgrading sheds legacy compatibility code and keeps Kibana on the actively maintained Redux majors.</p><p>RTK v2 also brings genuinely useful new features, including inline selectors in <code>createSlice</code> and opt-in inline async thunks through a customized <code>buildCreateSlice</code> setup, along with a <code>combineSlices</code> API with slice reducer injection for code splitting. That last one is particularly interesting for Kibana's plugin architecture where lazy-loading is the norm.</p><h2>How Redux is used across the Kibana monorepo</h2><p>Before diving into the solution, it's worth understanding just how varied Redux usage is across Kibana. A full audit of the codebase (tracked in <a href="https://github.com/elastic/kibana/issues/239863">#239863</a>) revealed several distinct camps:</p><p><strong>Pattern</strong></p><p><strong>Plugins and packages</strong></p><p><strong>What the migration needs</strong></p><p>Redux Toolkit v1</p><p>Discover, Lens, Synthetics, Security Solution</p><p>Full v1 to v2 migration</p><p>Plain Redux v4</p><p>Canvas, Maps, Index Management, Cross-Cluster Replication</p><p><code>redux-v4</code> alias only, no RTK migration</p><p>Kea</p><p>Enterprise Search (150+ files), Content Connectors</p><p><code>react-redux-v7</code> alias, no RTK migration</p><p><code>redux-saga</code></p><p>Synthetics, Graph, Uptime</p><p>Store setup only, saga is version-independent</p><p><code>typescript-fsa</code></p><p>Security Solution data-table package</p><p>Out of scope</p><p>Types and single imports</p><p>Expressions, Monitoring</p><p>Alias swap only</p><p>Plugins such as Discover, Lens, Synthetics, and Security Solution use RTK v1 APIs,including <code>createSlice</code>, <code>configureStore</code>, <code>createAsyncThunk</code>, and <code>createSelector</code>. These are the ones that actually need the v1 to v2 migration. But even here, complexity varies wildly. Lens uses stand-alone <code>getDefaultMiddleware</code> (removed in v2) and <code>PreloadedState</code> (also removed). Security Solution is the largest consumer at 300+ files, mixing modern RTK with legacy plain Redux patterns.</p><p>Canvas, Maps, Index Management, Cross-Cluster Replication, and several others still use plain Redux v4via <code>createStore</code>, <code>combineReducers</code>, <code>applyMiddleware</code>, and <code>connect</code>, which are classic patterns from the pre-RTK era. These don't need RTK migration at all since they're not using it  in the first place, but they do need the <code>redux-v4</code> alias since the default <code>redux</code> package is now v5.</p><p>Enterprise Search and Content Connectors use <code>kea</code>, a Redux abstraction layer with its own logic builders (<code>kea()</code>, <code>useValues</code>, <code>useActions</code>). There are more than 150 files in Enterprise Search alone. RTK migration isn't applicable here, since <code>kea</code> is its own world. But it <em>does</em> depend on <code>react-redux</code> v7 under the hood, which is where the bundler tricks come in.</p><p>Synthetics, Graph, and Uptime use <code>redux-saga</code> for side effects. Saga integration is actually independent of the RTK version, but these plugins need their store setup migrated.</p><p>The Security Solution data-table package uses <code>typescript-fsa</code> and <code>typescript-fsa-reducers</code> instead of RTK entirely, with its reducer embedded into Security Solution's main store, and isn’t part of the RTK migration at all.</p><p>The Expressions plugin only imports <code>shallowEqual</code> from <code>react-redux</code>, and Monitoring only imports types. These just need an alias swap.</p><p>Asking every team to migrate simultaneously was a nonstarter. The breaking changes in RTK v2 include stricter type checking and removed APIs, like <code>enableES5()</code> from immer, <code>getDefaultMiddleware</code> and <code>PreloadedState</code> gone entirely, <code>AnyAction</code> replaced by <code>UnknownAction</code>, and behavioral changes in how middleware is configured.</p><h2>Running Redux Toolkit v1 and v2 side by side</h2><p>The solution was to flip the typical migration pattern on its head. Instead of keeping the default imports on v1 and introducing v2 under aliases, the default package names (for example, <code>@reduxjs/toolkit</code>, <code>react-redux</code>, and <code>redux</code>) now point to v2. The old versions live under versioned aliases:</p><ul><li><p><code>redux-toolkit-v1</code></p></li><li><p><code>react-redux-v7</code></p></li><li><p><code>redux-v4</code></p></li><li><p><code>immer-v9</code></p></li><li><p><code>reselect-v4</code></p></li><li><p><code>redux-thunk-v2</code></p></li></ul>{
"@reduxjs/toolkit": "2.12.0",
"redux-toolkit-v1": "npm:@reduxjs/toolkit@1.9.7",
"react-redux": "9.2.0",
"react-redux-v7": "npm:react-redux@7.2.8"
}<p>This is npm's alias syntax. <code>"react-redux-v7": "npm:react-redux@7.2.8"</code> installs the old version under a different name. Both versions coexist in <code>node_modules</code> without conflicts.</p><p>The insight here is that all existing code in this pull request (PR) was moved to v1 aliases. Every <code>import { useSelector } from 'react-redux'</code> became <code>import { useSelector } from 'react-redux-v7'</code>. That's ~1,100 files touched, but the vast majority (~1,000) are mechanical one-liner import swaps. When a team is ready to migrate to v2, they switch back to the default import names. Once all v1 aliases disappear from the codebase, the old packages can be removed entirely.</p><p>This avoids the alternative, where v2 imports would end up under nonstandard names permanently, leaving nonstandard imports in the codebase for the long term.</p><h2>Serving both versions through the bundler</h2><p>Getting two versions of the same library to coexist at runtime is where things got interesting. Kibana uses <code>kbn-ui-shared-deps-npm</code> to bundle common dependencies as shared webpack externals. This needed to serve both the new v2 packages <em>and</em> the v1 aliases so that both are available at runtime.</p><h3>Pinning @elastic/charts with yarn resolutions</h3><p>Then there's <code>@elastic/charts</code>. It depends on RTK v1 internally and can't just be upgraded independently since it's an upstream package. Yarn resolutions pin its nested dependencies to v1 versions:</p>{
"@elastic/charts/@reduxjs/toolkit": "npm:@reduxjs/toolkit@1.9.7"
}<p>A <code>NormalModuleReplacementPlugin</code> in the shared deps webpack config detects when an import of <code>immer</code>, <code>@reduxjs/toolkit</code>, <code>redux</code>, <code>react-redux</code>, or <code>reselect</code> originates from within <code>@elastic/charts</code> and redirects resolution to the nested v1 copies. This ensures that <code>@elastic/charts</code> resolves to its compatible v1 dependency set.</p><h3>Keeping Kea on React Redux v7 with webpack externals</h3><p>The <code>kea</code> library was another fun case. It declares <code>react-redux</code> as a peer dependency (<code>&gt;= 7</code>), so without special handling its imports resolve to Kibana's default v9 package. The migration keeps Kea consumers on <code>react-redux-v7</code>, so Kea must use that same React context. The fix uses function-based webpack/rspack externals that skip externalizing <code>react-redux</code> when the import comes from <code>node_modules/kea</code>, combined with a <code>NormalModuleReplacementPlugin</code> that rewrites it to <code>react-redux-v7</code>. This ensures that <code>kea</code> uses the v7 React context that matches the <code>&lt;Provider&gt;</code> wrapping its consumers.</p><p>Both the webpack (<code>kbn-optimizer</code>) and the rspack (<code>kbn-rspack-optimizer</code>) configs needed these changes, with a shared <code>isKeaReactReduxImport</code> helper extracted to keep the logic consistent.</p><h2>Using an ESLint rule to prevent cross-version imports</h2><p>With two versions available, accidental cross-version imports are the biggest risk. A new <code>@kbn/imports/no_redux_toolkit_v2_imports</code> ESLint rule catches any import of the v2 default packages (such as <code>@reduxjs/toolkit</code>, <code>react-redux</code>, or <code>redux</code>, among others) in code that hasn't been migrated yet. It even auto-fixes them to the v1 aliases for file imports and Jest mock paths.</p><p>The rule is scoped via an override in <code>.eslintrc.js</code> to the ~36 plugin and package paths currently using v1. When a team migrates, they simply remove their path from the override list. This clean, self-service approach requires no coordination.</p>// .eslintrc.js (simplified)
overrides: [{
  files: [
'src/platform/plugins/shared/discover/**/*.{ts,tsx}',
'src/platform/plugins/shared/workflows_management/**/*.{ts,tsx}',
// ... 34 more paths
],
  rules: {
'@kbn/imports/no_redux_toolkit_v2_imports': 'error',
  },
}]<h2>Why mixing React Redux v7 and v9 breaks the context</h2><p>This is worth calling out because it's an easy failure mode to miss during an upgrade. <code>react-redux</code> v9 and v7 create separate React contexts. If a component tree has a v9 <code>&lt;Provider&gt;</code> at the top but a child component calls <code>useSelector</code> from v7 (or vice versa), React-Redux cannot find the matching context. In development, it throws an error explaining that the component must be wrapped in a matching <code>&lt;Provider&gt;</code>; in production, the missing context causes a runtime error when the hook accesses the store.</p>Error: could not find react-redux context value; please ensure the component is wrapped in a &lt;Provider&gt;<p>This means that each plugin needs to be explicitly pinned to one version. Shared packages that use <code>react-redux</code> can only be consumed by code on the same version, since mixing isn't possible. This is a constraint that makes the migration inherently per plugin rather than per file.</p><h2>Migration batches: What can move independently</h2><p>The dual-version setup gives every team a clear path forward, and the dependency graph analysis from the tracking issue identified natural migration batches:</p><ul><li><p><strong>Batch 1: Independent, self-contained stores.</strong> Packages like <code>kbn-coloring</code>, <code>transform</code>, <code>timelines</code>, and <code>expandable-flyout</code> have fully internal Redux stores with no types leaking through their public APIs. These can be migrated independently by their owning teams, with minimal risk.</p></li></ul><ul><li><p><strong>Batch 2: Coupled packages.</strong> Some packages share RTK types across boundaries and <em>must</em> migrate together. The machine learning (ML)/artificial intelligence for IT operations (AIOps) chain is one example: <code>@kbn/ml-response-stream</code> exports a <code>streamSlice</code> (a <code>createSlice</code> return value) that <code>@kbn/aiops-log-rate-analysis</code> embeds directly into its <code>configureStore</code>. Migrating one without the other causes type mismatches between v1 and v2 slice types. Similar coupling exists across the Lens ecosystem. The Lens plugin depends on <code>@kbn/coloring</code> (which has its own RTK store), <code>@kbn/lens-embeddable-utils</code>, and <code>@kbn/lens-common</code>, while itself being consumed by 40+ packages and plugins across chart expressions, visualizations, Maps, Canvas, and observability plugins. Whether Redux types leak through a package's public API determines if it can be migrated independently or needs coordination. <code>kbn-coloring</code>'s store is internal to its React components so it's safe to migrate alone, but other coupling points need careful analysis.</p></li></ul><ul><li><p><strong>Batch 3+: The big ones.</strong> Discover, Security Solution, and Lens each have their own migration timelines. Security Solution's 300+ files and mix of RTK with plain Redux v4 and <code>typescript-fsa</code> make it the largest effort, but the different patterns can be addressed independently. Lens has the trickiest v2 breaking changes around middleware configuration; stand-alone <code>getDefaultMiddleware</code> and <code>PreloadedState</code> are both removed in v2, and it has four custom middleware files with complex typing.</p></li></ul><p>Beyond the batched migrations:</p><ul><li><p><strong>Deprecated features</strong> can stay on v1 aliases. When the feature is removed, the v1 imports disappear through code deletion, without any migration work.</p></li><li><p><strong>Plain Redux v4 plugins</strong> (Canvas, Maps, and others) are entirely out of scope for RTK migration. They'd benefit from modernization, but that's a separate initiative.</p></li><li><p><strong>Kea plugins</strong> need <code>react-redux-v7</code> to <code>react-redux</code> alias updates eventually, but no RTK migration. The longer-term question (whether to keep Kea or migrate to RTK v2) is a separate decision.</p></li><li><p><strong>The dual-version approach</strong> adds measurable bundle overhead during the transition. It’s a trade-off but is acceptable for the migration period.</p></li></ul><h2>Lessons for other large monorepo upgrades</h2><p>The ESLint rule turned out to be the linchpin. Without automated enforcement, aliased imports would drift back to default names within weeks. With it, the migration state is visible in the paths listed in the override. As of the initial PR, zero files import from <code>@reduxjs/toolkit</code> v2. Every RTK usage goes through the <code>redux-toolkit-v1</code> alias. That's the starting line.</p><p>The preparation work also reached beyond import paths. Jest mocks referencing <code>react-redux</code> needed updating to <code>react-redux-v7</code>, as did Storybook previews, test helpers, and ambient type declarations. Multiple rounds of <code>node scripts/eslint_all_files --no-cache --fix</code> caught the mechanical cases; the remaining cases needed manual fixes.</p><p>If you're facing a similar major dependency upgrade in a large monorepo, the pattern of giving the new version the default name and the old version an explicit alias is worth considering. New code naturally uses the current version, while older usage stays visible and trackable until it reaches zero.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/redux-toolkit-v2-migration-kibana-monorepo</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/redux-toolkit-v2-migration-kibana-monorepo</guid>
    <category><![CDATA[Inside Elastic]]></category>
    <category><![CDATA[Developer Experience]]></category>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Walter Rafelsberger]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3fa3c79a7e246c89/6a9111235c3126655043df06/unnamed.png" length="0" type="image/png"/>
    <pubDate>Fri, 28 Aug 2026 15:20:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Kibana Dashboards API: A stable contract for every panel type, tested by 50+ teams before GA]]></title>
    <description><![CDATA[Manage Kibana dashboards as code: Commit to Git, promote across environments, and automate deployments with the Kibana API and Terraform.]]></description>
    <content:encoded><![CDATA[<p>The<a href="https://dashboardsapispec.kibana.dev/dashboards#tag/Dashboards"> Kibana Dashboards and Visualizations APIs</a> are production-ready in Elastic 9.5, available across all subscription tiers, with full backward compatibility. Define your dashboards as JSON, commit them to Git, and then deploy across environments using continuous integration and continuous deployment (CI/CD) pipelines,<a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard"> Terraform</a>, or whatever tooling you already have. Over 50 teams tested the API during<a href="https://www.elastic.co/search-labs/blog/kibana-dashboards-as-code-terraform-api"> technical preview in 9.4</a>, some already running it in production. Version 9.5 also adds new endpoints (in technical preview) for<a href="https://dashboardsapispec.kibana.dev/tags.html"> Tags</a>, with<a href="https://dashboardsapispec.kibana.dev/markdowns.html"> Markdown</a> and<a href="https://dashboardsapispec.kibana.dev/links.html#tag/Links"> Links</a> panel endpoints available now in Elastic Cloud Serverless and landing in 9.6.</p><h2>What backward compatibility means for the Kibana Dashboards API</h2><p>During technical preview, the API shape could change between releases.[1] That's no longer the case. General availability (GA) means:</p><ul><li><p><strong>Complete backward compatibility.</strong> New fields and panel types will be added over time, but existing fields and behavior remain unchanged. Any future breaking changes would be very carefully considered and would only be introduced in a new major stack version.</p></li><li><p><strong>Production-ready with full support.</strong> The API carries Elastic's full support guarantees. You can safely use it in production environments for automated deployments, environment promotion, and programmatic dashboard management.</p></li></ul><h2>New Kibana API endpoints for Tags, Markdown, and Links panels</h2><p>Elastic 9.5 also introduces a new  standalone endpoint for <a href="https://dashboardsapispec.kibana.dev/tags.html"><strong>Tags</strong></a>, which let you categorize and filter dashboards. Now you can manage them programmatically through dedicated CRUD endpoints, making it easier to organize dashboards at scale across environments.	</p><p>New <a href="https://dashboardsapispec.kibana.dev/markdowns.html"><strong>Markdown</strong></a> and <a href="https://dashboardsapispec.kibana.dev/links.html#tag/Links"><strong>Links</strong></a> panel endpoints are available now in Serverless and will land in the next stack release (9.6).</p><h2>What panel types does the Kibana Dashboards API support?</h2><p>The Dashboards API supports all <em>by-value</em> panels in 9.5 (those defined directly in a dashboard, as opposed to library panels saved for reuse). Every supported panel type has a typed, validated schema.</p><p><strong>Panel type</strong></p><p><strong>Status</strong></p><p>XY charts</p><p>Supported</p><p>Metrics</p><p>Supported</p><p>Pie</p><p>Supported</p><p>Gauge</p><p>Supported</p><p>Heatmap</p><p>Supported</p><p>Data tables</p><p>Supported</p><p>Treemap</p><p>Supported</p><p>Discover sessions</p><p>Supported</p><p>Controls</p><p>Supported</p><p>Markdown</p><p>Supported</p><p>Links</p><p>Supported</p><p>ML panels</p><p>Supported</p><p>Observability panels</p><p>Supported</p><p>Maps</p><p>Coming soon</p><p>Vega</p><p>Coming soon</p><h2>How to manage Kibana dashboards as code</h2><p>The Dashboards API enables a full dashboards-as-code workflow: Export a dashboard as clean, diffable JSON, commit it to Git as the source of truth, review changes in pull requests, and deploy the same definition across development, staging, and production. Once a dashboard is managed as code, treat Git as the single source of truth: Changes made directly in the UI are overwritten the next time you deploy.</p><p>The main challenge when moving a dashboard between spaces, clusters, or stages is that dashboards reference objects like data views and library visualizations by ID. Because these IDs are auto-generated and differ across environments, a dashboard exported from one environment can point at objects that don't exist in another. There are three ways to handle this, listed here from most to least automated:</p><ul><li><p><strong>Use Terraform.</strong> The <a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard">Elastic Stack Terraform provider</a> tracks each resource and maps IDs per environment automatically, so references stay consistent as you promote a dashboard from development to production.</p></li><li><p><strong>Define by-value </strong><a href="https://www.elastic.co/docs/explore-analyze/visualize/esorql"><strong>Elasticsearch Query Language (ES|QL) panels</strong></a><strong>.</strong> The most portable way to build a panel is to define its visualization with ES|QL directly in the dashboard. An <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql-kibana">ES|QL</a> query reads from the indices you name in it, so the panel carries no external references to data views or library objects. The result is a fully self-contained, portable dashboard.</p></li><li><p><strong>Assign matching IDs.</strong> If you reference saved objects, like data views or library visualizations, create them with a chosen ID using <code>PUT</code> (upsert) rather than <code>POST</code> (which auto-generates an ID). Use human-readable IDs, like <code>logs-prod</code>, so they're easy to reuse and recognize across environments.</p></li></ul><p>For a detailed walkthrough of these portability patterns and the full dashboards-as-code workflow, see the <a href="https://www.elastic.co/docs/explore-analyze/dashboards/manage-dashboards-as-code#dashboards-as-code-portability">Manage dashboards as code</a> documentation.</p><h3>Create a Kibana dashboard with the Dashboards API using PUT</h3><p>Here's a quick example creating a dashboard with a metric panel using <code>PUT</code> instead of <code>POST</code> to assign a custom ID using the dashboard name (<code>service-health-overview</code>). The same logic works for creating standalone visualizations saved in the library.</p>PUT kbn:/api/dashboards/service-health-overview
{
  "title": "Service health overview",
  "description": "Key service metrics — managed via API",
  "tags": [
    "production",
    "sre-team"
  ],
  "panels": [
    {
      "type": "vis",
      "grid": {
        "x": 0,
        "y": 0,
        "w": 12,
        "h": 8
      },
      "config": {
        "title": "Error rate (5xx)",
        "type": "metric",
        "data_source": {
          "type": "esql",
          "query": "FROM logs-* | WHERE http.response.status_code &gt;= 500 | STATS error_rate=count(*) BY host.name"
        },
        "metrics": [
          {
            "type": "primary",
            "column": "count"
          }
        ]
      }
    }
  ]
}<h2>Kibana Dashboards API roadmap: Maps, Vega, and standalone endpoints</h2><p>We're actively expanding the API surface. Maps and Vega panel support is next, adding typed schemas for them. We're also building standalone CRUD endpoints for Discover sessions (beyond their existing support as dashboard panels), Vega, Maps, and Annotations, decoupled from the dashboard lifecycle.</p><p>For the full schema definitions, visit the <a href="https://dashboardsapispec.kibana.dev/dashboards#tag/Dashboards">Dashboards API documentation</a>. For Terraform users, the <a href="https://registry.terraform.io/providers/elastic/elasticstack/latest/docs/resources/kibana_dashboard">Elastic Stack Terraform provider</a> supports the GA Dashboards API.</p><h2>Note</h2><ol><li><p>The core endpoints are unchanged from the technical preview. If you built integrations against 9.4, they work in 9.5. The only breaking changes are two minor ones affecting dashboard listing and duration unit formats, documented <a href="https://www.elastic.co/docs/release-notes/kibana/breaking-changes">here</a>.</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/dashboards-as-code-kibana-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/dashboards-as-code-kibana-api</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[Developer Experience]]></category>
    <category><![CDATA[Integrations]]></category>
    <dc:creator><![CDATA[Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ed7e33de291f255/6a730619c8b7ac02b251f9d3/image1.png" length="0" type="image/png"/>
    <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Close enough is fast enough: How ES|QL Fast mode makes Kibana dashboards up to 100x faster]]></title>
    <description><![CDATA[Fast mode samples a fraction of the data instead of scanning all of it. This release also brings click-to-filter for ES|QL charts, query-powered controls, and cleaner metric and bar chart layouts.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch Query Language (ES|QL) STATS queries on Kibana dashboards now run up to 100x faster. ES|QL Fast mode, in general availability (GA) in Kibana 9.5, samples a fraction of the data rather than scanning every row, and results stay within a 90% confidence interval. With Fast mode, ES|QL charts pick up click-to-filter and Discover drilldowns. Plus, controls can pull their values from an ES|QL query, and metric and bar chart defaults are cleaner. This builds on the dashboard improvements<a href="https://www.elastic.co/search-labs/blog/kibana-dashboards-improvements"> shipped in 9.4</a>. The <a href="https://www.elastic.co/search-labs/blog/dashboards-as-code-kibana-api">Dashboards API</a> and <a href="https://www.elastic.co/search-labs/blog/ai-dashboards-kibana-vega-lite">AI dashboards and Vega-Lite charts</a> also go GA in this release.</p><h2>ES|QL charts performance and interactivity in Kibana dashboards</h2><h3>How ES|QL Fast mode runs dashboard queries up to 100x faster</h3><p>For common analytical tasks, like trend tracking, top-host identification, and capacity overviews, trading a small margin of accuracy for dramatically faster results is the right call, especially since not every question needs an exact answer.</p><p><a href="https://www.elastic.co/search-labs/blog/fast-approximate-esql-part-1">Elastic Search 9.4 introduced approximate ES|QL queries</a> as a syntax-only command in technical preview. Now, 9.5 makes approximation GA and adds<a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql-kibana#esql-kibana-fast-mode-toggle"> <strong>Fast mode</strong></a>, a UI toggle in Dashboards and Discover that enables<a href="https://www.elastic.co/docs/reference/query-languages/esql/esql-query-approximation"> approximate ES|QL STATS queries</a> without writing any query syntax. This makes Kibana one of the first tools to offer smart sampling with automatic extrapolation as a simple switch.</p><p>Fast mode is an Enterprise-only feature and is off by default. Dashboard authors can save their preferred state with the dashboard, and individual queries can override the toggle with <code>SET approximation=true</code> or <code>false</code> inline.</p><p>When switched on, ES|QL STATS queries target a fixed sample size (defaulting to 1,000,000 rows for grouped aggregations and 100,000 rows otherwise) rather than scanning the full dataset.<a href="https://www.elastic.co/search-labs/blog/fast-approximate-esql-part-1"> Benchmarks show heavy aggregations running up to 100x faster</a> on large datasets, with results that are typically highlyaccurate, defaulting to a 90% confidence interval. Approximation only applies to STATS commands where results can remain accurate. When accuracy cannot be ensured (such as with small datasets or aggregations like MAX, MIN, or COUNT_DISTINCT), Kibana automatically falls back to exact execution, even with Fast mode enabled.</p><p>Further improvements to how charts communicate that results are approximate are coming in future releases.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt473f75b25868afa1/6a719ccf75ed4699484a85dc/image2.png" alt="Kibana Fast mode toggle set to ON showing the approximation tooltip on a dashboard with metric panels" /><h3>Click-to-filter and Discover drilldowns for ES|QL charts</h3><p>Two of the most popular interactions for data view charts are also landing now for ES|QL-based visualizations.</p><ul><li><p><strong>Discover drilldowns</strong> now work on ES|QL panels. When a user clicks a data point or uses Explore in Discover, filters are translated to ES|QL <code>WHERE</code> clauses and Kibana Query Language (KQL) queries are carried over automatically. </p></li><li><p><strong>Click-to-filter also works for renamed fields:</strong> if your query renames a column (<code>STATS BY node = k8s.node.name</code>), Kibana now resolves the alias back to the indexed field, so the filter applies correctly.</p></li><li><p><strong>Tooltips:</strong> When filtering genuinely can't work (for example, because the field was computed entirely within the query and doesn't exist in the index), Kibana now shows a tooltip explaining why, so users know that it's a query limitation.Beyond interactivity, ES|QL layers now have the same <strong>Use global filters</strong> toggle (gear icon on the layer header) as data-view-backed visualizations. When you turn it off, the layer's query runs independently of dashboard-level filters, just like form-based layers already do. This is useful for reference lines, thresholds, or baselines that shouldn't change when you filter the dashboard. And ES|QL metric charts now support a background chart, matching the styling option already available for data view metrics.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt960ef7848c551ff0/6a719cfc3931bc448f28de69/image9.gif" alt="Kibana dashboard in edit mode with Host, OS, Cloud Provider and Region controls populated by ES|QL queries" /><p>Beyond interactivity, ES|QL layers now have the same <strong>Use global filters</strong> toggle (gear icon on the layer header) as data-view-backed visualizations. When you turn it off, the layer's query runs independently of dashboard-level filters, just like form-based layers already do. This is useful for reference lines, thresholds, or baselines that shouldn't change when you filter the dashboard. And ES|QL metric charts now support a background chart, matching the styling option already available for data view metrics.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf557d2a4578741bc/6a719e42e35d0253ce0312ec/image8.gif" alt="Kibana dashboard showing metric charts with Default density layout and preset style templates applied" /><p></p><p>Upcoming releases aim to keep adding the remaining functionality to ES|QL visualizations, such as multilayer support and saving visualizations to the library.</p><h3>Identify which Kibana panels use an ES|QL variable</h3><p><a href="https://www.elastic.co/search-labs/blog/kibana-dashboard-interactivity-variable-controls-overview">Variable controls</a> are among the most popular ES|QL-only features, since they let you parameterize chart queries to switch between fields, time intervals, or groupings without duplicating panels. On a dashboard with many panels and controls, though, it can be hard to tell which visualizations a variable actually affects. In edit mode, you can now click an ES|QL variable control's label to identify all related panels that consume the variable. Variables with no related panels display a warning to make it easier to audit wiring before saving.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e565e80cda5cfce/6a71a13eb966e1768c63d81b/image5.gif" alt="Kibana dashboard with Host, OS and Cloud Provider controls filtering CPU and memory charts in view mode" /><h2>Kibana metric and bar chart layout defaults</h2><h3>Metric chart preset layouts and density options</h3><p>The metric chart appearance panel now offers preset layouts: <strong>Top</strong>, <strong>Middle</strong>, <strong>Bottom</strong>, and <strong>Custom</strong>. When you pick a template, the layout snaps into place. If you need fine-grained control, switch to <strong>Custom</strong>.</p><p>Metrics used to pack values tightly, which is great for data-dense dashboards but hard to scan when a metric stands alone. Elastic Cloud 9.5 adds a <strong>Density</strong> style option under <strong>Style &gt; Details &gt; Other</strong>, with two presets: <strong>Compact</strong> (the previous layout) and <strong>Default</strong> (more padding, larger typography). Newly created metrics use <strong>Default</strong>, and existing saved charts keep <strong>Compact</strong> until you change them.</p><p><strong>Attribute</strong></p><p><strong>Compact</strong></p><p><strong>Default</strong></p><p>Padding</p><p>Tight, minimal spacing</p><p>More generous whitespace</p><p>Typography</p><p>Smaller text</p><p>Larger text</p><p>Best for</p><p>Data-dense dashboards with many metrics side by side</p><p>Standalone metrics or dashboards with fewer panels</p><p>New charts</p><p>Must be selected manually</p><p>Applied automatically</p><p>Existing charts</p><p>Preserved until changed</p><p>Must be selected manually</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7434a5894cd1a048/6a719e8478b5febf378f12bc/image6.gif" alt=" Kibana dashboard edit mode showing the Settings gear icon on an ES|QL metric panel with global filter controls" /><h3>Responsive bar chart labels in Kibana</h3><p>Labels in horizontal bar charts used to grow unchecked, so on smaller screens, a chart with long category names could become unreadable. Bar labels now get a max width and middle-truncate automatically, so the beginning and end of a label stay visible even when the full text doesn't fit. This works by default, with no configuration needed. In 9.6, we’re planning many more improvements to bar charts and labels.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt85aa55cba5eb3a78/6a719ea65f2918842f13c2cb/image7.gif" alt="Before and after comparison of Kibana horizontal bar chart labels truncating responsively on smaller screens" /><h2>Kibana dashboard controls populated by ES|QL queries</h2><p><a href="https://www.elastic.co/docs/explore-analyze/visualize/add-controls#create-and-add-options-list-and-range-slider-controls">Controls</a> are the most user-friendly way to filter a dashboard, and most dashboards use them. One of the longest-standing requests from users has been the ability to prefilter the values that a control shows. ES|QL queries make that possible and open a much wider set of possibilities, like chaining controls in new ways using variables. Regardless of how the values are populated, controls filter every panel on the dashboard, including ES|QL and data view visualizations.</p><p>Controls can now be populated from an ES|QL query instead of selecting a data view field directly. The <strong>Create control</strong> flyout adds a <strong>Select a field / Write a query</strong> toggle. You can write an ES|QL query that returns a single column and run it, and then the control derives its options from the result. Queries can reference dashboard <a href="https://www.elastic.co/docs/explore-analyze/visualize/add-variable-controls">variables</a> through the <code>?variable</code> syntax, enabling flexible chaining between controls.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltacb5b26c2b31f3e6/6a719ebdded0cff1f5f49290/image1.png" alt="Kibana Edit control flyout showing an ES|QL query populating a Host options list on a dashboard" /><h2>Coming soon: Progress bar visualization for Kibana tables</h2><p>A new progress bar visualization type is available in Elastic Cloud Serverless and is planned for general availability in 9.6. Progress bars show a value relative to a goal or maximum, which is useful for many O11y metrics, like CPUs, memory, or Service Level Agreement (SLA) tracking.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt991d8a3c7d03068d/6a719ed7c2c8edb0c708b82a/image4.png" alt="Kibana table visualization with progress bar cell decoration showing Average Bytes per request path" /><h2>What's next for Kibana dashboards and ES|QL visualizations</h2><p>Upcoming releases will keep pushing on better defaults, improving the ES|QL visualization experience, and adding new chart types. If you have a pain point or a feature request, select <strong>Submit feedback</strong> in the top menu; we're listening.</p><h2>How to try ES|QL Fast mode and the new Kibana dashboard features</h2><p>If you use <a href="https://www.elastic.co/cloud/serverless">Elastic Cloud Serverless</a>, you may already be using these changes. Otherwise, upgrade to 9.5, and then create a dashboard or open an existing one. Many updates apply automatically to new visualizations, while layout and style options appear in edit mode. If you aren't on Elastic Cloud yet, <a href="https://cloud.elastic.co/registration">start a trial</a> and explore the latest Kibana dashboards there.</p><p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-dashboards-esql-fast-mode</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-dashboards-esql-fast-mode</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[Analytics]]></category>
    <dc:creator><![CDATA[Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8b0336f51b4694f0/6a719cab5e874b5b0e1ab976/image3.png" length="0" type="image/png"/>
    <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Prompt to dashboard in under a minute, 5x cheaper: AI dashboards and custom Vega-Lite charts in Kibana]]></title>
    <description><![CDATA[Describe your metrics in natural language and Kibana's AI chat generates ES|QL-backed dashboards and Vega-Lite charts, from scatter plots to conditional formatting and custom tooltips.]]></description>
    <content:encoded><![CDATA[<p>Kibana's<a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/chat"> AI chat</a> now builds full<a href="https://www.elastic.co/docs/explore-analyze/visualize/esorql"> Elasticsearch Query Language–backed (ES|QL-backed)</a> dashboards from a natural-language prompt in under a minute. In Elastic 9.5, this moves to general availability (GA) (<a href="https://www.elastic.co/search-labs/blog/ai-dashboard-generation-elastic-agent-kibana">technical preview in 9.4</a>) with error recovery that retries failed queries, 5x lower ES|QL generation costs through tiered model routing, and interactive filter controls. This release also adds<a href="https://www.elastic.co/docs/explore-analyze/visualize/custom-visualizations-with-vega"> Vega-Lite</a> chart creation through natural language, including scatter plots, box plots, conditional formatting, and custom tooltips that you'd normally have to hand-code in JSON.</p><h2>What's new in Kibana's AI dashboard creation</h2><p><strong>Capability</strong></p><p><strong>Technical preview (9.4)</strong></p><p><strong>GA (9.5)</strong></p><p>Error handling</p><p>No retry on failed ES|QL queries</p><p>Automatic retry up to three times with query inspection and adjustment</p><p>ES|QL generation cost</p><p>All queries routed through the primary model</p><p>Tiered model routing, up to 5x cheaper</p><p>Time range</p><p>Fixed default window</p><p>Automatic selection based on data time distribution</p><p>Filter controls</p><p>Not supported</p><p>Automatically added for the most relevant fields</p><p>Vega-Lite charts</p><p>Not supported</p><p>Natural-language creation, including scatter plots, box plots, conditional formatting, custom tooltips</p><p>Chart editing</p><p>Not supported</p><p>Edit existing Vega-Lite panels through natural language</p><h3>Automatic error recovery for AI dashboard generation</h3><p>In the technical preview, the agent didn’t retry failed ES|QL queries. In 9.5, it detects query errors and retries up to three times, inspecting each error and adjusting the query before giving up. In practice, this eliminates the majority of empty-panel issues and produces dashboards that render correctly on the first try.</p><h3>Why is AI dashboard creation cheaper in Elastic 9.5?</h3><p>Not every step in dashboard generation needs the same level of reasoning. In 9.5, ES|QL generation routes through a lighter model by default and falls back to the primary model only when needed. If your <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/connectors">connector</a> uses Anthropic's Claude Opus 4.8, that means 5x cheaper for ES|QL generation across all panels.</p><h3>Automatic time range selection based on your data</h3><p>Dashboards are only useful when they show the right window of data. The agent now applies improved logic to pick a time range that makes sense for the data it's querying, unless the user asks for a specific time range. It considers the data's time distribution and adjusts accordingly, whether that means the last hour for a live incident or the last 90 days for a trend analysis, rather than defaulting to a fixed window.</p><h3>Automatic filter controls on AI-generated dashboards</h3><p>Dashboard creation now supports controls; that is, interactive filters that let viewers narrow a dashboard by field values without editing the underlying queries. When generating a dashboard, the agent automatically adds controls at the top for the fields most relevant to filter by.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4a5520e66ae76001/6a719a218a155220ed6498e7/image3.png" alt="Kibana AI chat generating an ES|QL-backed host metrics dashboard with automatic filter controls in 71 seconds" /><h2>Vega-Lite charts from natural language: Chart types and formatting beyond the defaults</h2><p><a href="https://vega.github.io/vega/">Vega</a> and <a href="https://vega.github.io/vega-lite/examples/">Vega-Lite</a> support a wide range of chart types and customizations in Kibana. With 9.5, you can build them from plain language instead of writing the code yourself. </p><h3>Scatter plots, box plots, and more Vega-Lite chart types</h3><p>Scatter plots, box plot charts, faceted small multiples, bubble charts, and composition charts (like combining histograms with heatmaps), among many others, are supported by <a href="https://vega.github.io/vega-lite/examples/">Vega-Lite</a>. A prompt like <em>Show me a scatter plot of response time vs. request size, colored by service name</em> produces a Vega-Lite panel with the right data mappings. They use Kibana's default color palettes to blend with the rest of the dashboard.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf1651fe7ac903d47/6a719a49f124649f746fc1b4/image5.png" alt="Kibana dashboard with four Vega-Lite charts: box plot, bubble chart, faceted small multiples, and heatmap." /><h3>Conditional formatting, custom tooltips, and labels on standard charts</h3><p>Even for chart types that are already native to dashboards, like bar, line, or area, sometimes you need more control than the default capabilities offer. Vega-Lite through the chat fills that gap. Some examples include:</p><ul><li><p><strong>Conditional color formatting:</strong> Color data points above a threshold differently; for example, turning data points in a line or bars red when some metric spikes beyond your Service Level Objective (SLO). Ask the agent something like <em>Turn any points above 500ms red for my line chart.</em> </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc1211784e9033557/6a719a6ab966e1736163d7d1/image1.png" alt="Vega-Lite line and bar charts in Kibana with conditional colour formatting showing data points above a threshold in red" /><p></p></li><li><p><strong>Custom marks and labels:</strong> Add emojis, symbols, or inline text labels to data points for at-a-glance status indicators.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3c59c3748484bc1/6a719aa02888394fdc07bac1/image2.png" alt="Lite horizontal bar chart in Kibana with emoji flag labels and custom tooltip showing requests by country" /><p></p></li><li><p><strong>Custom tooltips:</strong> Enrich hover states with additional metrics, context, or computed values that aren't part of the chart's axes. Ask something like <em>Add a tooltip that shows total record counts and the % per bar.</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt43f241f4382b5b90/6a719ab7ded0cf3367f49275/image4.png" alt="Vega-Lite stacked bar chart in Kibana with custom tooltip showing total records and percentage of total by extension" /><p></p></li></ul><p>This also works for editing existing Vega charts. If you have a Vega-Lite panel that needs a tweak like changing a color scale, adjusting an axis, or switching the mark type, describe the change in chat instead of digging into the JSON code.</p><h2>How we built natural-language Vega-Lite generation in Kibana</h2><p>Generating a Vega-Lite chart from a sentence is not a one-shot <em>ask the model for JSON</em> prompt. We built a small agentic pipeline that turns natural-language intent into a validated, data-backed chart.</p><p>When a request comes in, the agent first determines whether Vega-Lite is the right fit. For Vega-Lite requests, it grounds the visualization in a real ES|QL query against Elasticsearch and then uses a model to generate the Vega-Lite code. Before rendering, the result goes through a normalization layer that corrects the schema and binds the canonical query. It also applies render-safety transformations. </p><p>A few design choices make this workflow reliable:</p><ul><li><p><strong>Typed tool calling</strong>: Chart creation is a structured tool invocation rather than free-form Vega-Lite pasted into the conversation.</p></li><li><p><strong>Constrained generation</strong>: The model generates Vega-Lite code within a defined schema, making the output more predictable and easier to validate.</p></li><li><p><strong>Curated examples:</strong> Structural patterns, such as faceting, layered marks, and heatmaps, provide guidance without copying the underlying data.</p></li><li><p><strong>Execute-and-verify loops</strong>: Queries are executed before chart authoring, and validation failures trigger corrective retries for ES|QL generation.</p></li></ul><h2>Try AI dashboard creation and Vega-Lite charts in Kibana</h2><p>To try natural-language dashboard creation and Vega-Lite charts, upgrade to <strong>Elastic 9.5</strong> (or <a href="https://cloud.elastic.co/registration">start a free trial</a>), and open the <strong>chat</strong> in Kibana. Then ask it to build a dashboard from your data. For Vega-Lite, try asking for a chart type you've wanted but never built, like a scatter plot or a bubble chart. If the result isn't quite right, tell the agent what to change. It iterates with you.</p><p>This requires an Enterprise license. <a href="https://www.elastic.co/docs/explore-analyze/ai-features/agent-builder/chat#get-started">Get started</a>.</p><p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-dashboards-kibana-vega-lite</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-dashboards-kibana-vega-lite</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Marta Bondyra,Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt54406ad0378bc5fc/6a7199ffed03ccee0dac9d7c/image6.png" length="0" type="image/png"/>
    <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[137,000 people, zero human decisions: agentic disaster response with Elasticsearch]]></title>
    <description><![CDATA[Find out how a Kibana detection rule, a workflow and an AI agent automatically relocated 137,000 military personnel across seven installations when a hurricane hit, no dispatcher required.]]></description>
    <content:encoded><![CDATA[<p>Elastic just coordinated the automated evacuation of 137,000 military personnel across seven installations, with no human in the loop. A Category 4 hurricane hits the Hampton Roads coastline. Elasticsearch's geospatial enrichment identifies every facility in the impact zone at index time. A Kibana detection rule fires. A workflow starts an AI agent conversation. The agent reasons through capacity, distance and branch compatibility, then dispatches 16 evacuation and intake notifications in a single pass. From raw GDACS event to coordinated action, automatically.</p><p>Every year, natural disasters force emergency managers, military commanders, and public safety officials to make high-stakes decisions in compressed time frames. These decisions traditionally rely on phone trees, spreadsheets, and institutional knowledge spread across dozens of people. The coordination overhead alone costs critical time.</p><p>This post demonstrates how Elastic can power a responsive, agentic coordination system for disaster response that detects a threat, reasons through the logistics, and takes action automatically. To make it concrete, we built a simulation: a fictitious Category 4 hurricane threatening the Hampton Roads coastline triggers the automated relocation of over 137,000 personnel across seven military installations.</p><p><strong>Disclaimer:</strong> <strong>This is an entirely fictitious scenario built for demonstration purposes. </strong>Hurricane ELARA-26 doesn’t exist. Installation locations are based on real, publicly available geographic data (the U.S. Department of Defense [DoD] Military Installations, Ranges, and Training Areas [MIRTA] dataset), but all operational data, like personnel counts, housing capacity, assets, contact emails, and mission profiles, are completely fabricated. Nothing in this demo reflects actual military readiness, capability, or operational procedures.</p><h2>Why automated disaster response requires geospatial and agentic coordination</h2><p>When a natural disaster threatens critical infrastructure, the coordination challenge is immediate:</p><ul><li><p>Which facilities are in the impact zone?</p></li><li><p>How many personnel need to move?</p></li><li><p>Where can they go, and do those facilities have capacity?</p></li><li><p>Who needs to be notified right now?</p></li></ul><p>These questions don't wait. Neither should the answers.</p><h2>Deploy the pipeline: prerequisites and setup</h2><p>Follow the instructions <a href="https://github.com/tehbooom/elastic_natural_disaster/blob/main/README.md">here in the example repo</a> to deploy a local Elastic cluster with Elastic Inference Service (EIS) via <a href="https://www.elastic.co/docs/explore-analyze/elastic-inference/connect-self-managed-cluster-to-eis#set-up-eis-with-cloud-connect">Cloud Connect</a>.</p><h2>How the Elasticsearch agentic disaster response pipeline works</h2><p>The pipeline has seven layers that work together end to end:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf09bfae87ab35bec/6a4693ef31bdbbe3ef8b33ae/61814cddea0409162fb057c2113e0a496c105238-1999x275.png" alt="Pipeline flowchart Alt text: Horizontal flowchart with seven labeled boxes connected by arrows: GDACS feed, ingest pipeline, enrich (geo_shape), detection rule, workflow, AI agent, and email." /><ol><li><p><strong>Data ingestion:</strong> Global Disaster Alert and Coordination System (GDACS) disaster events sent to Elasticsearch</p></li><li><p>I<strong>ngest pipeline</strong>: GeoJSON is ingested and normalized to Elastic Common Schema (ECS).</p></li><li><p><strong>Geospatial enrichment:</strong> The event's affected area polygon is matched against indexed military installation boundaries.</p></li><li><p><strong>Alerting:</strong> A Kibana detection rule fires when a disaster intersects any installation.</p></li><li><p><strong>Workflow automation:</strong> The alert triggers a Kibana workflow that starts an AI agent conversation.</p></li><li><p><strong>AI reasoning:</strong> The agent reasons through affected facilities, their assets, and nearest supporting facilities to determine relocation of all assets and personnel.</p></li><li><p><strong>Email notifications</strong>: The agent dispatches emails to all recipients for incoming and outgoing personnel and or assets.</p></li></ol><p>Let's walk through each layer.</p><h2>Step 1: Indexing military installations with geo boundaries</h2><p>The foundation is the DoD MIRTA dataset from <a href="https://source.coop/seerai/hifld/military-installations-ranges-and-training-areas-mirta-dod-sites---boundaries">source.coop/seerai/hifld</a>. This dataset provides a <code>geo_shape</code> of type <code>Point</code> for each installation; centroid coordinates rather than full boundary polygons.</p><p>Each installation document in the <code>mitra-facilities</code> index is enriched with operational profile data (all fictitious), beyond what MIRTA provides:</p>{
  "entity_name": "Naval Station Norfolk",
  "branch_of_service": "Navy",
  "mission_function_type": "fleet_support",
  "personnel_count": 50000,
  "housing_capacity": 55000,
  "temporary_housing_capacity": 10000,
  "logistics_capabilities": ["fuel", "airlift", "sealift", "medical"],
  "available_assets": [
    { "type": "helicopters", "count": 24 },
    { "type": "transport_vehicles", "count": 150 }
  ],
  "contact_email": "norfolk.ops@navy.mil.gov.fake",
  "operational_status": "act",
  "is_joint_base": false,
  "entity_geo_location": { "type": "polygon", "coordinates": [...] }
}<p>This rich index is what enables the AI agent to make intelligent allocation decisions; not just "here are nearby bases," but "here are bases with available housing capacity, compatible mission types, and the logistics to receive incoming assets."</p><h2>Step 2: Ingesting and normalizing GDACS events</h2><p>GDACS publishes real-time GeoJSON for earthquakes, tropical cyclones, floods, wildfires, volcanoes, and droughts. We ingest this feed into a data stream (<code>logs-gdacs.events-*</code>) using a custom ingest pipeline that normalizes the raw GeoJSON to ECS fields.</p><p>The GDACS ingest pipeline does several things worth noting:</p><p><strong>Geometry extraction:</strong> The centroid is stored as a <code>geo_point</code> for map display, and the impact polygon is stored as a <code>geo_shape</code> in <code>gdacs.affected_area</code>, which is the field used for intersection queries later.</p><p><strong>Severity normalization:</strong> Each disaster type has a different severity scale. A tropical cyclone is measured in km/h wind speed; an earthquake in Richter magnitude. The pipeline maps all of them to a normalized 0–100 score:</p>// Painless snippet from the ingest pipeline
if (type == 'TC') {
  norm = Math.min(100.0, Math.max(0.0, (val - 40.0) / 2.6));
} else if (type == 'EQ') {
  norm = Math.min(100.0, Math.max(0.0, (val - 4.0) * 20.0));
}<p>The normalized severity score then maps to a <code>severity_level</code> label (<code>low</code>, <code>medium</code>, <code>high</code>, <code>critical</code>) used for alert severity mapping in the detection rule.</p><p><strong>ECS alignment:</strong> <code>event.kind: alert, event.category: threat</code>, timestamps mapped to <code>event.start/event.end</code>, and a stable fingerprint-based <code>_id</code> for deduplication.</p><h2>Step 3: Geospatial enrichment: Finding affected facilities at index time</h2><p>Elasticsearch's geo_match enrich policy matches the disaster polygon against every installation boundary at index time, with no query-time join required. Instead of querying at search time, we use an <strong>enrich processor</strong> in the ingest pipeline to match the disaster's impact polygon against every installation boundary <em>as the document is indexed</em>.</p><p>The enrich policy is a <code>geo_match</code> policy:</p>{
  "geo_match": {
    "indices": "mitra-facilities",
    "match_field": "entity_geo_location",
    "enrich_fields": [
      "entity_name",
      "entity_type",
      "entity_station_number",
      "entity_geo_city_name",
      "entity_geo_region_name"
    ]
  }
}<p>The processor runs at the end of the ingest pipeline:</p>{
  "enrich": {
    "policy_name": "facilities-geo",
    "field": "gdacs.affected_area",
    "target_field": "affected_facilities",
    "shape_relation": "INTERSECTS",
    "max_matches": 128
  }
}<p><code>INTERSECTS</code> catches any installation whose boundary touches or overlaps the disaster polygon and even partial intersections. The result is that every GDACS event document is stored with an <code>affected_facilities</code> nested array that tells us exactly which installations are in the impact zone. No join query needed.</p><h2>Step 4: Detection rule: Alerting on facility impact</h2><p>A Kibana detection rule watches the <code>logs-gdacs.events-*</code> data stream and fires when a GDACS event has been enriched with at least one affected facility:</p>Query: affected_facilities: { entity_name: * }<p>The rule runs on an hourly schedule (covering a <code>now-1h</code> to <code>now</code> window) and uses dynamic severity mapping; the <code>gdacs.severity_level</code> field computed by the ingest pipeline drives the alert severity automatically.</p><p>Alert severity also drives the risk score via field mapping:</p>"risk_score_mapping": [
  {
    "field": "gdacs.normalized_severity",
    "operator": "equals",
    "value": ""
  }
]<p>When the rule fires, it passes the full alert context, including the enriched <code>affected_facilities</code> array with installation names, types, and locations, downstream to a Kibana workflow.</p><h2>Step 5: Workflow automation: Bridging alert to agent</h2><p>Kibana Workflows handle the handoff from detection to response. The natural disaster response workflow is triggered by the alert:</p>triggers:
  - type: alert
steps:
  - name: start_convo
    type: kibana.request
    with:
      method: "POST"
      path: "/api/agent_builder/converse"
      body:
        agent_id: "mitra.response"
        input: "New Natural Disaster Alert: {{ event.alerts | json }}"<p>The entire alert payload (disaster type, severity, affected area, and the list of impacted installations) is forwarded to the AI agent as its initial context. The agent takes it from there.</p><h2>Step 6: The AI agent: From data to coordinated action</h2><p>The <code>mitra.response</code> agent takes the full alert payload and, in a single agentic loop, assesses scope, finds receiving facilities, allocates personnel and dispatches evacuation and intake notifications, all without human intervention.</p><p>The agent has two tools available:</p><ul><li><p><strong><code>mitra.nearest_facility</code></strong>queries the <code>mitra-facilities</code> index using a geo_shape query, sorted by distance from a given coordinate, returning up to 50 nearby active installations with available capacity.</p></li><li><p><strong><code>mitra.send_email</code></strong> iterates over a JSON array of facility objects and dispatches formatted evacuation or receiving notifications.</p></li></ul><p>The agent's instruction set defines a clear workflow:</p><ol><li><p><strong>Assess the situation.</strong> Parse the alert, identify affected facilities, and determine disaster scope.</p></li><li><p><strong>Inventory what needs to move.</strong> Personnel counts, critical assets, housing requirements per facility.</p></li><li><p><strong>Find destination facilities.</strong> Call <code>mitra.nearest_facility</code> for each affected installation, filtering out facilities still in the danger zone.</p></li><li><p><strong>Make allocation decisions.</strong> Reason through single versus multi-facility solutions, branch compatibility, housing capacity, asset support.</p></li><li><p><strong>Send coordination emails.</strong> Dispatch evacuation orders to source facilities and intake notifications to receiving facilities.</p></li><li><p><strong>Produce a summary report. </strong>Produces a short summary of all affected facilities, total personnel, assets moved, destination facilities, and any concerns to the chat for review.</p></li></ol><p>The agent's allocation logic follows real-world constraints: Don't exceed housing capacity, prefer same-branch relocations when possible, use joint bases for multi-branch overflow, and prioritize distance to minimize transit time.</p><h3>The nearest facility tool</h3><p>The underlying workflow query uses <code>geo_shape</code> with a circle filter and <code>_geo_distance</code> sorting:</p>"query": {
  "bool": {
    "filter": [
      {
        "geo_shape": {
          "entity_geo_location": {
            "shape": {
              "type": "circle",
              "coordinates": [{{ inputs.lon }}, {{ inputs.lat }}],
              "radius": "5000km"
            },
            "relation": "intersects"
          }
        }
      },
      { "term": { "operational_status.keyword": "act" } }
    ]
  }
},
"sort": [
  {
    "_geo_distance": {
      "entity_geo_point": { "lat": {{ inputs.lat }}, "lon": {{ inputs.lon }} },
      "order": "asc",
      "unit": "km"
    }
  }
],
"script_fields": {
  "available_capacity": {
    "script": {
      "source": "Math.max(0, doc['housing_capacity'].value - doc['personnel_count'].value)"
    }
  }
}<p>Available capacity is computed at query time via a script field which calculates housing capacity minus current personnel count. The agent uses this to allocate personnel across destinations without exceeding limits.</p><h2>Hurricane ELARA-26: agentic coordination of 137,000 personnel, end to end</h2><p>Hurricane ELARA-26 is a Category 4 storm (213 km/h maximum winds) projected to make landfall in the Hampton Roads area of Virginia. When the GDACS event is ingested, the affected area polygon intersects seven major military installations in the region. The detection rule fires. The workflow kicks off an agent conversation.</p><p>Within a single agentic loop, the agent:</p><ul><li><p>Identified seven facilities in the impact zone, with a combined 137,372 personnel.</p></li><li><p>Called <code>mitra.nearest_facility</code> to find receiving facilities outside the storm track.</p></li><li><p>Distributed personnel across nine receiving facilities based on available housing capacity and distance.</p></li><li><p>Generated and dispatched evacuation orders to all seven affected installations.</p></li><li><p>Generated and dispatched intake notifications to all nine receiving facilities.</p></li><li><p>Produced a full coordination summary, similar to below:</p></li></ul><p><strong>Facilities evacuated:</strong></p><p>Facility</p><p>Personnel</p><p>Naval Station Norfolk</p><p>50,000</p><p>Joint Expeditionary Base Little Creek-Fort Story</p><p>18,000</p><p>Naval Air Station Oceana</p><p>15,355</p><p>Naval Air Station Oceana Dam Neck Annex</p><p>17,509</p><p>NG State Military Reservation Camp Pendleton</p><p>9,707</p><p>Joint Base Langley-Eustis</p><p>15,000</p><p>Naval Weapons Station Yorktown</p><p>11,801</p><p><strong>Receiving facilities:</strong></p><p>Facility</p><p>Distance</p><p>Incoming personnel</p><p>Fort Gregg-Adams</p><p>97 km</p><p>~40,000</p><p>Marine Corps Base Quantico</p><p>148 km</p><p>~30,000</p><p>Naval Support Facility Indian Head</p><p>151 km</p><p>~30,000</p><p>Joint Base Andrews</p><p>180 km</p><p>~30,000</p><p>Naval Air Station Patuxent River</p><p>141 km</p><p>~10,000</p><p>NG MTA Camp Butner</p><p>174 km</p><p>~5,000</p><p>NG Bethany Beach Training Site</p><p>209 km</p><p>~4,707</p><p>Rivanna Station</p><p>140 km</p><p>~7,500</p><p>Def Gen Supply Center</p><p>22 km</p><p>~6,000</p><p>Assets relocated include transport vehicles, helicopters, patrol boats, medical units, engineering vehicles, generators, water trailers, shelter kits, and communication systems.</p><h3>Automated email notifications</h3><p>Once the agent finalized its allocation plan, it called <code>mitra.send_email</code> and dispatched 16 emails in a single pass; that is, evacuation orders to all seven affected installations and intake notifications to all nine receiving facilities. Each message included destination facility, incoming personnel count, assets to move, and a coordination contact. What would have taken hours of phone trees completed automatically the moment the agent finished reasoning.</p><h3>Extending agentic disaster response with RAG and policy grounding</h3><p>This demo is purely from structured data, like capacity numbers, distances, and operational status. Elastic's semantic search and retrieval augmented generation (RAG) capabilities can make the agent significantly smarter, with two additions:</p><p><strong>Historical response retrieval:</strong> Index past after-action reports, Federal Emergency Management Agency (FEMA) incident summaries, and disaster response records as vector embeddings. When a new event fires, the agent can semantically retrieve how similar events were handled, informing allocation decisions with institutional knowledge rather than capacity math alone.</p><p><strong>Policy and doctrine grounding:</strong> Index DoD emergency management directives, installation continuity of operations plans, and commander guidance. The agent can retrieve and cite the actual policies governing a response, ensuring every decision is grounded in doctrine rather than inference.</p><p>Both follow the same Elastic-native approach:; An inference pipeline generates embeddings at index time, and a semantic search tool is exposed to the agent. The coordination pipeline stays the same. The agent just gets smarter.</p><h2>Why Elasticsearch is the right platform for agentic public sector response</h2><p>This isn’t a chatbot. It isn’t a dashboard. It's a responsive agentic workflow system, one that detected a threat, reasoned through a complex logistics problem, and coordinated the relocation of 137,000 people without a human in the loop. That kind of outcome is only possible because every capability it depends on lives in a single, unified platform.</p><p>Elasticsearch's geospatial support (<code>geo_point</code>, <code>geo_shape</code>, enrichment policies, and distance-based sorting) handles the spatial reasoning that makes intersection detection and facility lookup possible at scale. Semantic search and vector embeddings ground agents in truth, ensuring AI reasoning is based on what's actually in your data rather than hallucinated assumptions. Kibana's detection engine, Workflows, Agent Builder, and Agent Builder tools wire it all together into a pipeline that goes from raw event to coordinated action with no external glue code required.</p><p>No other platform brings this together the way Elastic does. The combination of real-time indexing, geospatial precision, semantic retrieval, and agentic orchestration, all in one stack, with enterprise-grade security and observability built in, is what separates Elastic from tools that do one of these things well but require you to stitch the rest together yourself.</p><h2>Agentic geospatial response for emergency management, fire, law enforcement and public health</h2><p>The same architecture applies wherever people, facilities, and real-time events intersect. The specific data changes. The pipeline doesn't.</p><p><strong>Emergency management:</strong> FEMA and state offices of emergency management can map shelter locations, staging areas, and vulnerable populations against incoming National Weather Service (NWS) severe weather polygons, triggering automated resource pre-positioning before a storm makes landfall.</p><p><strong>Fire and emergency medical services:</strong> Fire departments can overlay unit locations and response zones against wildfire perimeters or structure fire clusters, automatically routing mutual aid requests to the nearest available units with the right equipment.</p><p><strong>Law enforcement:</strong> Agencies can correlate active incident locations with school zones, critical infrastructure, and officer positions, triggering geo-aware lockdown notifications or resource dispatch without waiting for manual triage.</p><p><strong>Public school safety:</strong> School districts can monitor real-time threat feeds against campus boundaries. When a threat intersects a school's perimeter, an agent can immediately notify administration, initiate lockdown communications, and coordinate law enforcement response, all before a dispatcher picks up a phone.</p><p><strong>Public health:</strong> Health departments can match disease surveillance data or environmental hazard zones against clinic locations, population density layers, and supply depot inventories to route resources where they're needed most.</p><p>Sector</p><p>Use case</p><p>Elastic capability</p><p>Emergency management</p><p>Match shelter locations against NWS severe weather polygons</p><p>geo_shape enrichment + Kibana Workflows</p><p>Fire and EMS</p><p>Overlay unit locations against wildfire perimeters</p><p>geospatial routing + nearest-facility query</p><p>Law enforcement</p><p>Correlate incidents with school zones and officer positions</p><p>geo-aware alert rules + agent dispatch</p><p>Public school safety</p><p>Monitor threat feeds against campus perimeters</p><p>detection rules + automated notification</p><p>Public health</p><p>Match hazard zones against clinic locations and supply depots</p><p>semantic search + geospatial enrichment</p><p>The data is different in every scenario. The underlying pattern of ingest, enrich at index time, detect intersection, trigger agentic response, and act is all the same. Elastic gives public sector organizations the platform to build it once and adapt it everywhere.</p><p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-agentic-disaster-response</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-agentic-disaster-response</guid>
    <category><![CDATA[Agentic AI]]></category>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Alec Carpenter]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt969cad2694920de4/6a4693f37746672ad42675b5/cb292a501835472598dee30bef25c77afc54db6c-720x420.png" length="0" type="image/png"/>
    <pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Kibana cuts dashboard load time by up to 25% - here's the polling strategy behind it]]></title>
    <description><![CDATA[Find out how Kibana uses continuous polling and browser-side HTTP/2 detection to cut dashboard load times by up to 25%, with automatic fallback on HTTP/1.]]></description>
    <content:encoded><![CDATA[<p>Kibana dashboards and Discover now load up to 25% faster thanks to continuous polling. Instead of sleeping between periodic checks, Kibana now keeps HTTP connections open and delivers Elasticsearch query results the moment they're ready. On HTTP/2+ (the Kibana default since 9.0) this kicks in automatically with no configuration required. On HTTP/1, Kibana falls back to traditional polling to prevent connection pool exhaustion.</p><h2>How Kibana fetches data when loading a dashboard</h2><p>When a Dashboard is opened, most of the panels (internally, we call these <em>embeddables</em>) kick off one or more Elasticsearch queries. But instead of the simple call-and-response of a synchronous (sync) search, we use the power of asynchronous (async) search (<a href="https://www.elastic.co/docs/solutions/search/async-search-api">docs</a>).</p><p>With async search, query results are kept available in Elasticsearch outside of any particular HTTP request. This is important because it</p><ul><li><p>makes data loading resilient to network turbulence</p></li><li><p>powers our <a href="https://www.elastic.co/docs/explore-analyze/discover/background-search">background search feature</a> which allows users to work on other things in Kibana while they wait for a long-running dashboard or Discover session</p></li></ul><p>After the initial query is submitted, Kibana monitors the search to detect when it is complete and retrieve the result set.</p><h3>How traditional polling affects Kibana dashboard load times</h3><p>In traditional polling, Kibana submits a query, closes the initial connection, then periodically checks Elasticsearch for completion.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt093ed1a718d2f2ed/6a1710c28b73cb568118a109/2f44064a2e627866e129eb626f68ddd62230a4e2-1999x719.png" alt="Diagram showing traditional polling in Kibana. The Kibana timeline shows a short connection-open period after query submission, followed by a long sleeping period, then a brief poll for status, then results delivered. The Elasticsearch timeline runs a query that completes midway through Kibana's sleep period, illustrating the coordination gap that causes lost time." /><p>We do give Elasticsearch a short amount of time after query submission to simply complete the search and return results. If the search completes that quickly, it amounts to a simple call-and-response. But for longer searches, the initial connection is closed and Kibana begins periodically checking the search for completion. This is called <em>polling</em>.</p><h4>Performance drawbacks of traditional polling</h4><p>Looking at the figure above, perhaps you can already see the performance drawback to this approach: the search is most likely to finish during one of Kibana’s sleep intervals, leading to lost time.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3685326f1aa90a1b/6a1710c30c4857892b01ab7a/ad8b80d9e8d6d774065d62e352aad47c3ddb4686-1999x719.png" alt="Timeline diagram showing the performance cost of traditional polling. The Kibana timeline shows a connection-open period, a long sleep period, a poll for status, then results delivered. The Elasticsearch timeline shows the query completing midway through Kibana's sleep, followed by a red lost-time segment - the wasted duration before Kibana wakes up and retrieves the results." /><p>In the worst case scenario (when a search completes at the beginning of a sleep period) the entire duration of the polling interval will be wasted.</p><h4>The impact of a backoff strategy</h4><p>It’s standard practice when polling to apply a backoff strategy. This means that the longer the duration of the search, the less frequently we poll.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt37fb76cf22647ee5/6a1710c5a929cf6fcaae0abd/77665de4a0fd166b533a2c2c55f6f28e38cf37ce-1200x338.png" alt="Horizontal bar chart showing Kibana's polling interval backoff schedule by query duration. Queries under 1.5 seconds use an interval of roughly 0.5 seconds; 1.5–5 second queries use 1 second; 5–20 second queries use approximately 2.5 seconds; queries over 20 seconds use a 5-second polling interval." /><p>However, this also means that the potential lost time scales with the duration of the search.</p><h4>How polling intervals create sawtooth latency patterns</h4><p>Putting these factors together, our lost time becomes a stepwise sawtooth function.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4e81306b0c9f259/6a1710c147d49c34c42d8aec/d5cd43366f62de628c3a054ffb7bf0b05d7a1390-1500x600.png" alt="Line chart showing lost time in seconds versus query completion time in seconds, forming a sawtooth pattern where lost time rises then drops to zero repeatedly, with peaks growing from under 1 second to 5 seconds as query duration increases from 0 to 30 seconds." /><p>Here, the peaks are worst-case scenarios and the troughs are best case scenarios. This illustrates that traditional polling costs us between nothing and the full duration of the polling interval, depending on the search duration (and network conditions).</p><h2>Continuous polling: how Kibana eliminates wait time</h2><p>The problem with traditional polling is a fundamental lack of coordination between Kibana and Elasticsearch. Ideally, Kibana knows immediately when results are available. So, what if we inverted the polling pattern to where nearly all of the time is spent checking Elasticsearch and no time is spent sleeping?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4566eaaec79150c7/6a1710c78b73cb1df318a10d/7edc138528dfe1310df42f393ee7279fe3c4703b-1999x713.png" alt="Timeline diagram showing continuous polling in Kibana. The Kibana timeline is entirely blue - the connection stays open from query submission through two connection refreshes until results are delivered, with no sleep periods. The Elasticsearch timeline shows the query completing and results delivered immediately. The legend shows Lost time struck through, indicating it has been eliminated." /><p>With this combination of long polling and no more sleep periods, results are delivered as soon as they are ready.</p><h3>HTTP/1 degradation</h3><p>The theory is solid. So why does this Kibana deployment look so degraded when we turn on continuous polling?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltede864738a88e1cb/6a1710c947d49c178d2d8af2/517378a73d36bd95927b81b1f912ce465b7adf4c-800x412.gif" alt="Animated screen recording of a Kibana dashboard loading the Sample Logs Data dataset, showing multiple panels populating in sequence, including a response codes time series, a US map of total requests, unique visitors count, HTTP error rate metrics, and a Sankey chart of machine OS and destination data." /><p>The key is that this deployment is running over HTTP/1. In HTTP/1, HTTP requests are mapped 1:1 to TCP connections. So several long-lived polling requests are hogging the browser’s finite connection pool, causing other requests to be queued.</p><p>In HTTP/2+ on the other hand, network requests can share TCP connections via multiplexing, so we don’t run into this problem.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5cddb4d6767a1ccf/6a1710cb839dfa5056dcffcd/f60f3a37baf5ec16c9f1773f08855e7f9e3a7491-1536x1024.png" alt="Diagram comparing HTTP/1 and HTTP/2 for Kibana continuous polling. HTTP/1 requires one TCP connection per request, exhausting the browser's connection pool across six connections. HTTP/2 multiplexes multiple polling requests over a single TCP connection, avoiding pool exhaustion and maintaining performance." /><p>So, on HTTP/2+ continuous polling is a virtue but on HTTP/1 it becomes a vice.</p><p></p><p>HTTP/1</p><p>HTTP/2+</p><p>TCP connections</p><p>One per HTTP request</p><p>Multiplexed (many requests share connections)</p><p>Continuous polling behaviour</p><p>Degrades performance (connection pool exhaustion)</p><p>Full benefit (results delivered immediately)</p><h4>How Kibana detects HTTP protocol for optimal polling</h4><p>HTTP/2 is the recommended protocol and it’s the Kibana default since 9.0, so it would be a shame not to ship this performance enhancement. On the other hand, the HTTP/1 experience is so degraded that it isn’t acceptable to risk it on any on-prem deployments who haven’t yet upgraded their protocol. The answer is clear: we need to detect which protocol is in use and apply the optimal polling strategy.</p><p>It is certainly possible for the Kibana server to know which protocol it is speaking. But, there’s a catch: the limiting factor is the browser’s connection pool. That means that what really matters is what the <em>browser</em> is speaking.</p><p>Because of proxies, these are not always the same.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc61ff0abfe101eec/6a1710cd2867144b8893e412/13e38001fc4bd3fc60cfc69114fb9098fd745906-1970x786.png" alt="Architecture diagram showing three components in a horizontal chain: Kibana Server on the left, an optional Proxy in the centre, and Kibana Client on the right. The server-to-proxy hop is labelled with kibana.yml server.protocol, indicating the known protocol. The proxy-to-client hop is labelled with three question marks, indicating the protocol on that final hop is unknown and may differ." /><p>If we based our optimization on the server protocol, we could get things wrong in one of two ways.</p><ol><li><p>Apply continuous polling when we shouldn’t and degrade the experience.</p></li><li><p>Fail to apply continuous polling when we should and miss out on the optimization.</p></li></ol><p>Luckily, modern browsers provide a way to detect the protocol of the last network hop of any completed request through the use of a <code>PerformanceObserver</code>. So, we watch for the protocol of the first query submission and optimize based on that.</p>new PerformanceObserver((list) =&gt; {
  const entries = list.getEntries();
  const entry = entries.find(({ name }) =&gt; name.includes('/internal/search/'));
  if (entry) {
    this.protocolSupportsMultiplexing = ['h2', 'h3'].includes(entry.nextHopProtocol);
  }
});<h2>Lab results: continuous polling vs. traditional polling in Kibana</h2><p>To validate continuous polling, we created dashboards with query delays ranging from 1 to 23 seconds and measured load times with and without the optimization enabled. We then loaded the dashboards with and without continuous polling to measure the gains (we had a lot of fun with <a href="https://github.com/kertal/race-for-the-prize">race-for-the-prize</a>).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba4af840d8324923/6a1710ceb339d52fe076a0b6/5f19fb45c5307a7491037fe1ad1a302728793203-1200x742.png" alt="Bar chart showing lab test results for Kibana continuous polling: time saved versus traditional polling across query durations from 1 to 23 seconds. Savings vary between near-zero and 4.9 seconds depending on where queries complete relative to polling interval boundaries, confirming the sawtooth latency pattern predicted by the backoff schedule." /><p>The pattern echoes our original sawtooth diagram. For some query durations, the gains are small while for others they amount to several seconds.</p><h2>Conclusion</h2><p>This optimization successfully replaces the latency inherent in traditional polling with a more efficient continuous polling strategy. The primary challenge was implementing this optimization conditionally to prevent performance degradation on HTTP/1 deployments. We solved it using the browser’s <code>PerformanceObserver</code> to reliably detect the protocol in use for the final network hop.</p><p>Laboratory testing validates the theory, showing continuous polling delivers results as soon as they are ready. On average, this leads to a meaningful improvement in user experience, making data load up to 25% faster.</p><p>This work is the latest step in our commitment to driving down time-to-insight for our users. By making Kibana a more transparent proxy to Elasticsearch data, we push the limits of performance within our sphere of influence. More to come!</p><p>(In 2025, Thomas Neirynk gave an <a href="https://www.elastic.co/search-labs/blog/kibana-dashboard-rendering-time">excellent overview</a> of the methods and motivation behind improving Kibana dashboard performance. This is an update on that initiative.)</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-dashboard-performance-continuous-polling</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-dashboard-performance-continuous-polling</guid>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Drew Tate,Matthias Wilhelm]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4e81306b0c9f259/6a1710c147d49c34c42d8aec/d5cd43366f62de628c3a054ffb7bf0b05d7a1390-1500x600.png" length="0" type="image/png"/>
    <pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Kibana Alerting: Breaking past scalability limits & unlocking 50x scale]]></title>
    <description><![CDATA[Kibana Alerting now scales 50x better, handling up to 160,000 rules per minute. Learn how key innovations in the task manager, smarter resource allocation, and performance optimizations have helped break past our limits and enabled significant efficiency gains.]]></description>
    <content:encoded><![CDATA[<p>Kibana alerting has been the monitoring solution of choice for many large organizations over the last few years. As adoption has continued to grow, so has the number of alerting rules users have created to monitor their systems. With more organizations relying on Kibana for alerting at scale, we have seen an opportunity to improve efficiency and ensure sufficient performance for future workload needs.</p><p>Between Kibana 8.16 and 8.18, we tackled these issues head-on, introducing key improvements that shattered previous scalability barriers. Before these enhancements, Kibana Alerting could only support up to 3,200 rules per minute with at least 16 Kibana nodes before hitting significant performance bottlenecks. By Kibana 8.18, we’ve increased the scalability ceiling of rules per minute by 50x, supporting up to 160,000 lightweight alerting rules per minute. This was achieved by making Kibana efficiently scale beyond 16 Kibana nodes and increasing per-node throughput from 200 to up to 3,500 rules per minute. These enhancements make all alerting rules run faster, with fewer delays and more efficiently.</p><p>In this blog, we’ll explore the scaling challenges we overcame, the key innovations that made it possible, and how you can leverage them to run Kibana Alerting at scale efficiently.</p><h2>How Kibana Alerting scales with Task Manager</h2><p>Kibana Alerting allows users to define rules that trigger alerts based on real-time data. Behind the scenes, the Kibana Task Manager schedules and runs these rules.</p><p>The Task Manager is Kibana’s built-in job scheduler, designed to handle asynchronous background tasks separately from user interactions. Its key responsibilities include:</p><ul><li><p><strong>Running one-time and recurring tasks</strong> such as alerting rules, connector actions, and reports.</p></li><li><p><strong>Dynamically distributing workloads</strong> as Kibana background nodes join or leave the cluster.</p></li><li><p><strong>Keeping the Kibana UI responsive</strong> by offloading tasks to dedicated background processes.</p></li></ul><p>Each alerting rule translates into a recurring background task. Each background task is an Elasticsearch document, meaning it is stored, fetched and updated as an Elasticsearch document. As the number of alerting rules increases, so do the background tasks Kibana must manage. However, each Kibana node has a limit on how many tasks it can handle simultaneously. Once capacity is reached, additional tasks must wait, leading to delays and slower task run times.</p><h2>The problem: Why scaling was limited</h2><p>Before these improvements, Task Manager faced several scalability constraints, preventing it from scaling beyond 3,200 tasks per minute and 16 Kibana nodes. At this scale, we observed diminishing returns as contention and resource inefficiencies limited further scale. These numbers were based on internal performance testing using a basic Elasticsearch query alerting rule performing a no-op query. The diminishing returns observed included:</p><p><strong>Task claiming contention</strong></p><p>Task Manager uses a distributed polling approach to claim tasks within an Elasticsearch index. Kibana nodes periodically query for tasks and attempt to claim them using Elasticsearch’s <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/optimistic-concurrency-control.html">optimistic concurrency control</a>, which prevents conflicting document updates. If another node updates the task first, the original node drops it, reducing overall efficiency.</p><p>With too many Kibana nodes competing for tasks, document update conflicts increase drastically, limiting efficiency beyond 16 nodes and reducing system throughput.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt236fbb4a3a7689a7/6a170bb0286714697893e333/85114dc3fd052718e3713545a9870b76bdf87496-1600x676.png" alt="Kibana task claiming contention" /><p><strong>Inefficient per-node throughput</strong></p><p>Each Kibana node has a limit on the number of tasks that can run concurrently (default: 10 tasks at a time) to prevent memory and CPU overload. This safeguard often results in underutilized CPU and memory, requiring more nodes than necessary.</p><p>Additionally, the polling interval (default: 3000ms) defines how often Task Manager claims new tasks. A shorter interval reduces task delays but increases contention as nodes compete more for updates.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e7e41ddbb4fb894/6a170bb1acf08830b5be9b8c/bba5bd813853d106e62d041239a228ea236b3ebd-1600x495.png" alt="Kibana alerting Inefficient per-node throughput" /><p><strong>Resource inefficiencies</strong></p><p>When running a high volume of alerting rules, Kibana nodes perform repetitive Elasticsearch queries, repeatedly loading the same objects and lists for each alerting rule run, consuming more CPU, memory, and Elasticsearch resources than necessary. Scaling up requires costly infrastructure expansions to support the increasing request loads.</p><h2>Why it’s important</h2><p>Breaking these barriers is crucial for Kibana’s continued evolution. Improved scalability unlocks:</p><ul><li><p><strong>Cost optimization</strong>: Reducing infrastructure costs for large-scale operations.</p></li><li><p><strong>Faster recovery</strong>: Enhancing Kibana’s ability to recover from node or cluster failures.</p></li><li><p><strong>Future expansion</strong>: Enabling scalability for additional workloads, such as scheduled reports and event-driven automation.</p></li></ul><h2>Key innovations in Kibana Task Manager</h2><p>To achieve a 50x scalability boost, we introduced several innovations:</p><p><strong>Kibana discovery service: smarter scaling</strong></p><p>Previously, Kibana nodes were unaware of each other’s presence, leading to inefficient task distribution. The new Kibana discovery service dynamically monitors active nodes and assigns task partitions accordingly, ensuring even load distribution and reducing contention.</p><p><strong>Task partitioning: eliminating contention</strong></p><p>To prevent nodes from competing for the same tasks, we introduced task partitioning. Tasks are now distributed across 256 partitions, ensuring only a subset of Kibana background nodes attempt to claim the same tasks at any given time. By default, each partition is assigned to a maximum of two Kibana nodes, while a single Kibana node can be responsible for multiple partitions.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6bf10cb5ad39fa39/6a170bb314b27053e3e3c63e/3bfb8c38499e0794665bedcaf05c398bc2ceb6a7-1589x597.png" alt="Kibana Task Manager: Task partitioning" /><p><strong>Task costing: smarter resource allocation</strong></p><p>Not all background tasks consume the same resources. We implemented a task costing system that assigns task weights based on CPU and memory usage. This allows Task Manager to dynamically adjust the number of tasks to claim, optimize resource allocation, and ensure efficient performance.</p><p><strong>New task claiming algorithm</strong></p><p>The old algorithm relied on update-by-query with forced index refresh to identify claimed tasks. This approach was inefficient and introduced unnecessary load on Elasticsearch. The new algorithm avoids this by searching for tasks without requiring an immediate refresh. Instead, it performs the following operations on the task manager index; a <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html">_search</a> to find candidate tasks, followed by an <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">_mget</a> which returns documents that may have been updated more recently but are not yet reflected in the refreshed index state. By comparing document versions from <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html">_search</a> and <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">_mget</a> results, it discards mismatches before proceeding with bulk updates. This approach increases efficiency in Elasticsearch and offers finer control to support task costing.</p><p>By factoring in the poll interval, task concurrency and the index refresh rate, we can calculate the upper limit of expected conflicts and adjust the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html">_search</a> page size accordingly. This helps ensure enough tasks are retrieved so the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">_mget</a> doesn’t discard all the search results due to document version mismatches.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5a033a41792212f8/6a170bb4cf4f25ddd3b2d1a0/fa4a8238528ae0b337c764c3185b844b4ac14795-785x792.png" alt="Kibana Task Manager- New task claiming algorithm" /><p><strong>More frequent polling for tasks</strong></p><p>By ensuring a fixed number of nodes compete for the same tasks with task partitioning and a new lightweight task claiming algorithm, Task Manager can now poll for tasks more frequently without additional stress on Elasticsearch. This reduces delays between a task completing and the next one starting, increasing overall system throughput.</p><h2>Performance optimizations in Kibana Alerting</h2><p>Before our optimizations using Elastic <a href="https://www.elastic.co/observability/application-performance-monitoring">APM</a>, we analyzed alerting rule performance and found that the alerting framework required at least 20 Elasticsearch queries to run any alerting rule. After the optimizations, we reduced this to just 3 queries - an 85% reduction, significantly improving run times and reducing CPU overhead.</p><p>Additionally, Elasticsearch previously relied on the resource-intensive pbkdf2 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-settings.html#password-hashing-algorithms">hashing algorithm</a> for API key authentication, introducing excessive overhead at scale. We optimized authentication by switching to the more efficient SHA-256 algorithm, allowing us to eliminate the use of an internal Elasticsearch cache that was severely limited by the number of API keys used concurrently.</p><h2>Impact: How users are benefiting</h2><p>Early adoption has demonstrated:</p><ul><li><p><strong>50% faster rule run times</strong>, reducing overall system load.</p></li><li><p><strong>Increased task capacity</strong>, enabling more tasks to run on existing infrastructure.</p></li><li><p><strong>Fewer under-provisioned clusters</strong>, minimizing the need for scaling infrastructure to meet demand.</p></li></ul><p><strong>Drop in average task delay because of increased per-node throughput and making the cluster properly provisioned</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba942618abef6e61/6a170bb64a531b30b536a985/f576de7f6c29e27da636484d45cb7d7c1611135d-1600x314.png" alt="Kibana task manager: average task delay" /><p><strong>Drop in rule run duration because of alerting framework optimizations</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltce4d77fca3635ca9/6a170bb766c4f9cdf6f8c062/178d7d16abed458a20107e4582a4fc7243bcb1cc-1600x793.png" alt="Kibana task manager:  Drop in rule run duration" /><p><strong>Drop in Elasticsearch requests because of alerting framework optimizations</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt36def2b00a0297aa/6a170bb9a292991aa8d01047/e88ff1073e3c0f67bfaf842b4865ae6d588f8828-1117x609.png" alt="Kibana task manager: Drop in Elasticsearch requests" /><h2>Getting started: How to scale efficiently</h2><p>Upgrading to Kibana 8.18 unlocks most of these benefits automatically. For additional optimization, consider adjusting the <code>xpack.task_manager.capacity</code> <a href="https://www.elastic.co/guide/en/kibana/current/task-manager-settings-kb.html#task-manager-settings">setting</a> to maximize per-node throughput while ensuring p999 <a href="https://www.elastic.co/guide/en/kibana/current/configuring-monitoring.html">resource usage</a> remains below 80% for memory, CPU, and event loop utilization and below 500ms for event loop delay.</p><p>By default, Kibana has a guardrail of 32,000 alerting rules per minute. If you plan to exceed this limit, you can modify the <code>xpack.alerting.rules.maxScheduledPerMinute</code> setting accordingly.</p><p>The new <code>xpack.task_manager.capacity</code> setting makes Kibana handle workload distributions more effectively, making the following settings unnecessary in most cases and should be removed from your kibana.yml settings:</p><ul><li><p><code>xpack.task_manager.max_workers</code></p></li><li><p><code>xpack.task_manager.poll_interval</code></p></li></ul><p>If you’re running Kibana on-prem and want to isolate background tasks into dedicated nodes, you can use the <code>node.roles</code> <a href="https://www.elastic.co/guide/en/kibana/current/settings.html">setting</a> to separate UI-serving nodes from those handling background tasks. If you’re using Kibana on Elastic Cloud Hosted (ECH), scaling to 8GB or higher will automatically enable this isolation.</p><h2>What’s next for Kibana Alerting?</h2><p>We’re not stopping at 50x. Our roadmap aims for 100x+ scalability, further eliminating Elasticsearch bottlenecks.</p><p>Beyond scaling, we’re also focusing on improving system monitoring at scale. Upcoming integrations will provide system administrators with deeper insights into background task performance, making it easier to decide when and how to scale.</p><p>Additionally, with task costing, we plan to increase task concurrency for Elastic Cloud Hosted (ECH) customers when configured with more CPU and memory (e.g., Kibana clusters with 2GB, 4GB, or 8GB+ of memory).</p><p>Stay tuned for even more advancements as we continue to push the limits of Kibana scalability!</p><p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-alerting-task-manager-scalability</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-alerting-task-manager-scalability</guid>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Mike Cote]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltff8f9a2d63790904/6a170bbbcdacbf61eb7d2a26/86f6f563d9f1ee6929ce4afc9005dfacd93f2990-720x420.png" length="0" type="image/png"/>
    <pubDate>Fri, 18 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Export your Kibana Dev Console requests to Python and JavaScript Code]]></title>
    <description><![CDATA[The Kibana Dev Console now offers the option to export requests to Python and JavaScript code that is ready to be integrated into your application.]]></description>
    <content:encoded><![CDATA[<p>Have you used the Kibana Dev Console? This is a fantastic prototyping tool that allows you to build and test your Elasticsearch requests interactively. But what do you do after you have a working request in the Console?</p><p>In this article we'll take a look at the new code generation feature in the Kibana Dev Console, and how it can significantly reduce your development effort by generating ready to use code for you.</p><p>This feature is available in our Serverless platform and in Elastic Cloud and self-hosted releases 8.16 and up.</p><h2>The Kibana Dev Console</h2><p>This section provides a quick introduction to the <a href="https://www.elastic.co/guide/en/kibana/current/console-kibana.html">Kibana Dev Console</a>, in case you have never used it before. Skip to the next section if you are already familiar with it.</p><p>While you are in any part of the Search section in Kibana, you will notice a "Console" link at the bottom of your browser's page:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7c0bbd6964b0886d/6a170aeb6f7f04dfb991484b/e80850635ecc74536696743181afb3ac0c74e38f-1024x742.png" alt="The Kibana Dev Console - Open Console" /><p>When you click this link, the Console expands to cover the page. Click it again to collapse it.</p><p>In the left-side panel of the Dev Console, you can enter Elasticsearch requests, with the help of an interactive editor that provides auto-completion and checks your syntax. Some example requests are already pre-populated so that you have something to start experimenting with.</p><p>When the cursor is on a request, a "play" button appears to its right. You can click this button to send the request to your Elasticsearch server.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8e8bf8f61f065daa/6a170aed964cea4ffa08bb9b/520637e15cd03234aefd26502e42c80310b3734f-1006x230.png" alt="Kibana Dev Console Send Request" /><p>After you execute a request, the response from the server appears in the panel on the right.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8c9a61493ab010d9/6a170aef0e2e49de6d41a0e2/ef250921da3ff260a6f56d6d4745842096809564-1024x642.png" alt="Kibana Dev Console Response" /><h2>Code Export feature in Kibana Dev Console</h2><p>The Dev Console makes it easy to prototype your requests or queries until you get exactly what you want. But what happens next? If you need to convert the request to code so that you can incorporate it into your application, then you can save time using the new code export feature.</p><p>Next to the Play button you will find the three dot or "kebab" button, which opens a menu of options. The first option provides access to the code export feature. If you've never used this feature before, it will appear with a "Copy as curl" label.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt69fd88f2ae0eadae/6a170af02b835f8ca2f4b205/27fe3d5aa5874d094d26d35ff2188ccc0e435b9f-1272x476.png" alt="Kibana Dev Console Options Menu" /><p>If you select this option, your clipboard will be loaded with a <a href="https://curl.se/">curl</a> command that is equivalent to the selected request.</p><p>Now, things get more interesting when you click the "Change" link, which allows you to switch to a different target language. In this initial release, the code export adds support for Python and JavaScript. More languages are expected to be added in future releases.</p><p>You can now select your desired language and click "Copy code" to put the exported code in your clipboard. You can also change the default language that is offered in the menu.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt64d35579b66099a4/6a170af266c4f9d021f8c02d/dd4c2c94ea17ba74bae7cf05fbab4b3944cb37ed-1256x702.png" alt="Kibana Dev Console Select Language" /><p>The exported code is a complete script in the selected language, using the official Elasticsearch client for that language. Here is an example of how the <code>PUT /my-index</code> request shown above looks when exported to the Python language:</p>import os
from elasticsearch import Elasticsearch

client = Elasticsearch(
    hosts=["&lt;your-elasticsearch-endpoint-url-here"],
    api_key=os.getenv("ELASTIC_API_KEY"),
)

resp = client.indices.create(
    index="my-index",
)
print(resp)<p>To use the exported code follow these steps:</p><ul><li><p>Paste the code from the clipboard to a new file with the correct extension (<code>.py</code> for Python, or <code>.js</code> for JavaScript).</p></li><li><p>In your terminal, add an environment variable called <code>ELASTIC_API_KEY</code> with a valid API Key for your Elasticsearch cluster. You can <a href="https://www.elastic.co/guide/en/kibana/current/api-keys.html#create-api-key">create an API key</a> right in Kibana if you don't have one yet.</p></li><li><p>Execute the script with the <code>python</code> or <code>node</code> commands depending on your language, making sure the official Elasticsearch client is installed.</p></li></ul><p>Now you are ready to adapt the exported code as needed to integrate it into your application!</p><h2>Conclusion</h2><p>In this article you have learned about the new Code Export feature in the Kibana Dev Console. We hope this feature will streamline your development process with Elasticsearch!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-dev-console-code-export</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-dev-console-code-export</guid>
    <category><![CDATA[Python]]></category>
    <category><![CDATA[Javascript]]></category>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Miguel Grinberg]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt64d35579b66099a4/6a170af266c4f9d021f8c02d/dd4c2c94ea17ba74bae7cf05fbab4b3944cb37ed-1256x702.png" length="0" type="image/png"/>
    <pubDate>Wed, 30 Oct 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>