Flexible Boards introduce a new structure for organizing and displaying queries and Service Level Objectives (SLOs) in Honeycomb. You can migrate existing Boards to the Flexible Boards format using the Honeycomb UI, API, or Terraform.
Choose the migration method matching how you manage your Boards:
honeycombio_flexible_board
resource.On August 15, 2025, the Honeycomb API will stop supporting legacy Boards.
Any Board API calls that use "type": "classic"
or omit the type
field will fail.
By August 29, 2025, Honeycomb will automatically migrate any remaining legacy Boards to the Flexible Boards format. During this process, query captions will move into the corresponding query’s description field.
The UI is the easiest option if you manage Boards manually. To migrate a Board using the Honeycomb UI:
If you use the API to create or update Boards, you need to update your request payload to match the Flexible Board format.
The Flexible Board format introduces two key changes:
panels
field replaces the queries
and slos
fields.
To learn more about the panels
field, visit the Honeycomb API documentation.type
field, which represents the Board type, must be set to flexible
.
To learn more about the type
field, visit the Honeycomb API documentation."type": "classic"
or omit the type
field will fail.To migrate a Create Board or Update Board request:
type
:flexible
in your request payload.column_layout
style
queries
and slos
fields with panels
.layout_generation
and set it to auto
. This helps automate panel positions.In this example, we show you how to migrate a legacy Board API payload containing the queries
and slos
fields to a Flexible Board payload.
The example legacy Board payload is as follows:
{
"queries": [
{
"query_style": "graph",
"dataset": "My Dataset",
"query_id": "abc1234e",
"query_annotation_id": "e4c24a35",
"visualization_settings": {
"hide_compare": false,
"hide_hovers": false,
"hide_markers": false,
"utc_xaxis": false,
"overlaid_charts": false,
"charts": [
{
"chart_index": 0,
"chart_type": "default",
"log_scale": false,
"omit_missing_values": false
}
]
}
}
],
"slos": [
"BGfyxhFto",
"dF1URaPGL"
]
}
To convert the legacy Board payload:
Start with an empty panels
array:
{
"panels": []
}
Add your SLOs as panels.
Each slo
maps to a panel, so each SLO requires its own panel:
{
"panels": [
{
"type": "slo",
"slo_panel": {
"slo_id": "BGfyxhFto"
},
},
{
"type": "slo",
"slo_panel": {
"slo_id": "dF1URaPGL"
},
},
]
}
Add your queries as panels.
Each query
also requires its own panel:
{
"panels": [
{
"type": "slo",
"slo_panel": {
"slo_id": "BGfyxhFto"
},
},
{
"type": "slo",
"slo_panel": {
"slo_id": "dF1URaPGL"
},
},
{
"type": "query",
"query_panel": {
"query_id": "abc1234e",
"query_annotation_id": "e4c24a35",
"query_style": "graph",
"visualization_settings": {
"hide_compare": false,
"hide_hovers": false,
"hide_markers": false,
"utc_xaxis": false,
"overlaid_charts": false,
"charts": [
{
"chart_index": 0,
"chart_type": "default",
"log_scale": false,
"omit_missing_values": false
}
]
}
}
}
]
}
Add layout_generation
and set it to auto
. This helps automate panel positions.
{
"layout_generation": "auto",
"panels": [
{
"type": "slo",
"slo_panel": {
"slo_id": "BGfyxhFto"
},
},
{
"type": "slo",
"slo_panel": {
"slo_id": "dF1URaPGL"
},
},
{
"type": "query",
"query_panel": {
"query_id": "abc1234e",
"query_annotation_id": "e4c24a35",
"query_style": "graph",
"visualization_settings": {
"hide_compare": false,
"hide_hovers": false,
"hide_markers": false,
"utc_xaxis": false,
"overlaid_charts": false,
"charts": [
{
"chart_index": 0,
"chart_type": "default",
"log_scale": false,
"omit_missing_values": false
}
]
}
}
}
]
}
Once you update your API requests using this structure, you are ready to create and update Flexible Boards.
To migrate Boards defined in Terraform, update your Terraform configuration:
honeycombio_board
blocks with honeycombio_flexible_board
blocks.query
and slo
blocks to panel
blocks.In this example, we show you how to update a Terraform configuration file to convert a legacy Board to a Flexible Board.
The example legacy Board Terraform configuration file is as follows:
data "honeycombio_query_specification" "latency_by_userid" {
time_range = 86400
breakdowns = ["app.user_id"]
calculation {
op = "HEATMAP"
column = "duration_ms"
}
calculation {
op = "P99"
column = "duration_ms"
}
filter {
column = "trace.parent_id"
op = "does-not-exist"
}
order {
column = "duration_ms"
op = "P99"
order = "descending"
}
}
resource "honeycombio_query" "latency_by_userid" {
dataset = var.dataset
query_json = data.honeycombio_query_specification.latency_by_userid.json
}
resource "honeycombio_query_annotation" "latency_by_userid" {
dataset = var.dataset
query_id = honeycombio_query.latency_by_userid.id
name = "Latency by User"
description = "A breakdown of trace latency by User over the last 24 hours"
}
resource "honeycombio_board" "overview" {
name = "Service Overview"
description = "Information about Service Overview"
query {
caption = "Latency by User"
query_id = honeycombio_query.latency_by_userid.id
query_annotation_id = honeycombio_query_annotation.latency_by_userid.id
graph_settings {
utc_xaxis = true
}
}
slo {
id = var.slo_id
}
}
To convert the example configuration file:
Create a honeycombio_flexible_board
resource:
resource "honeycombio_flexible_board" "overview" {
}
Add your Board’s name and description to your new resource:
column_layout
and style
fields are not supported in the honeycombio_flexible_board
resource.resource "honeycombio_flexible_board" "overview" {
name = "Service Overview"
description = "Information about Service Overview"
}
Add SLO panels.
For each of your slo
blocks in honeycombio_board
resource, create an equivalent panel
block:
resource "honeycombio_flexible_board" "overview" {
panel {
type = "slo"
slo_panel {
slo_id = var.slo_id
}
}
}
Add query panels.
For each of your query
blocks in the honeycombio_board
resource:
panel
blockgraph_settings
blocks with visualization_settings
blocksThe honeycomb_board
legacy resource uses utc_xaxis
while the honeycomb_flexible_board
resource uses use_utc_xaxis
.
To learn more about these changes, visit the Honeycomb Terraform Flexible Boards documentation.
resource "honeycombio_flexible_board" "overview" {
panel {
type = "slo"
slo_panel {
slo_id = var.slo_id
}
}
panel {
type = "query"
query_panel {
query_id = honeycombio_query.latency_by_userid.id
query_annotation_id = honeycombio_query_annotation.latency_by_userid.id
visualization_settings {
use_utc_xaxis = true
}
}
}
}
Replace your old honeycombio_board
block with your new honeycombio_flexible_board
block.
Your final configuration should look similar to:
data "honeycombio_query_specification" "latency_by_userid" {
time_range = 86400
breakdowns = ["app.user_id"]
calculation {
op = "HEATMAP"
column = "duration_ms"
}
calculation {
op = "P99"
column = "duration_ms"
}
filter {
column = "trace.parent_id"
op = "does-not-exist"
}
order {
column = "duration_ms"
op = "P99"
order = "descending"
}
}
resource "honeycombio_query" "latency_by_userid" {
dataset = var.dataset
query_json = data.honeycombio_query_specification.latency_by_userid.json
}
resource "honeycombio_query_annotation" "latency_by_userid" {
dataset = var.dataset
query_id = honeycombio_query.latency_by_userid.id
name = "Latency by User"
description = "A breakdown of trace latency by User over the last 24 hours"
}
resource "honeycombio_flexible_board" "overview" {
name = "Service Overview"
description = "Information about Service Overview"
panel {
type = "slo"
slo_panel {
slo_id = var.slo_id
}
}
panel {
type = "query"
query_panel {
query_id = honeycombio_query.latency_by_userid.id
query_annotation_id = honeycombio_query_annotation.latency_by_userid.id
visualization_settings {
use_utc_xaxis = true
}
}
}
}
This example requires manual migration steps using the Honeycomb UI, and relies on import
/removed
blocks in Terraform.
The described migration process below will generate an initial configuration file that then can be adapted to replace your legacy Boards configuration file.
This approach will generate most Terraform elements for you, but you can refer to the previous example’s migration guide to change your honeycombio_board
to honeycombio_flexible_board
resource.
query
, query_annotations
, and/or slos
, ensure that you update the generated configuration file to remove the hardcoded ID and replace them with your existing dynamic logic.Before you begin, you will need:
This example legacy Board Terraform configuration file includes four different Boards:
terraform {
required_providers {
honeycombio = {
source = "honeycombio/honeycombio"
version = "~> 0.37.0"
}
}
}
resource "honeycombio_board" "overview" {
name = "Service Overview"
description = "My flexible board description"
query {
query_id = "pg_hHHnysmE3"
query_annotation_id = "vk_iEUQtbsuM"
query_style = "combo"
graph_settings {
utc_xaxis = true
}
}
slo {
id = "gb_vu8cL6Sef"
}
}
resource "honeycombio_board" "another_overview" {
name = "Another Service Overview"
description = "My second flexible board description"
query {
query_id = "pg_hHHnysmE3"
query_annotation_id = "vk_iEUQtbsuM"
query_style = "combo"
graph_settings {
utc_xaxis = true
}
}
slo {
id = "gb_vu8cL6Sef"
}
}
resource "honeycombio_board" "slo_only_overview" {
name = "SLO Only Board"
description = "My slo only board description"
slo {
id = "gb_vu8cL6Sef"
}
}
resource "honeycombio_board" "query_only_overview" {
name = "Query Only Board"
description = "My query onyl board description"
query {
query_id = "pg_hHHnysmE3"
query_annotation_id = "vk_iEUQtbsuM"
query_style = "combo"
graph_settings {
utc_xaxis = true
}
}
}
To start your migration process, locate and copy the board ID located in each Board’s URL, which is formatted similarly to:
https://ui.honeycomb.io/<team-name>/environments/<environment-name>/board/<board-id>/<board-name>
You will use this board ID to import via your Terraform configuration.
Here is how our example boards appear with their board IDs:
overview -> "3i_AHeVpefRW"
another_overview -> "Aq_Sbk6dvknb"
slo_only_overview -> "up_CzuDEizVS"
query_only_overview -> "wq_6sNVcYjMo"
Manually update your Terraform configuration with an import
block and a remove
block for each Board.
For our example, our updated Terraform configuration looks like:
terraform {
required_providers {
honeycombio = {
source = "honeycombio/honeycombio"
version = "~> 0.37.0"
}
}
}
removed {
from = honeycombio_board.overview
lifecycle {
destroy = false
}
}
import {
to = honeycombio_flexible_board.overview
id = "3i_AHeVpefRW"
}
removed {
from = honeycombio_board.another_overview
lifecycle {
destroy = false
}
}
import {
to = honeycombio_flexible_board.another_overview
id = "Aq_Sbk6dvknb"
}
removed {
from = honeycombio_board.slo_only_overview
lifecycle {
destroy = false
}
}
import {
to = honeycombio_flexible_board.slo_only_overview
id = "up_CzuDEizVS"
}
removed {
from = honeycombio_board.query_only_overview
lifecycle {
destroy = false
}
}
import {
to = honeycombio_flexible_board.query_only_overview
id = "wq_6sNVcYjMo"
}
Use the following command (and replace with your relevant variables) to generate your Terraform configuration:
HONEYCOMB_API_KEY=xxxx HONEYCOMB_API_ENDPOINT=http://localhost:8081 terraform plan -generate-config-out=<replace/any/path/of/your/choice>/migrated.tf
-generate-config-out
flag is an option that allows Terraform an auto-generated configuration file to dump at the specified path. In the above example, the new Terraform configuration will be dumped in migrated.tf
.After running the command, the output for our example looks like:
honeycombio_flexible_board.query_only_overview: Preparing import... [id=wq_6sNVcYjMo]
honeycombio_flexible_board.another_overview: Preparing import... [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.overview: Preparing import... [id=6E_cEMEDViGU]
honeycombio_flexible_board.slo_only_overview: Preparing import... [id=up_CzuDEizVS]
honeycombio_flexible_board.slo_only_overview: Refreshing state... [id=up_CzuDEizVS]
honeycombio_flexible_board.overview: Refreshing state... [id=6E_cEMEDViGU]
honeycombio_flexible_board.another_overview: Refreshing state... [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.query_only_overview: Refreshing state... [id=wq_6sNVcYjMo]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
# honeycombio_board.another_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "another_overview" {
id = "Aq_Sbk6dvknb"
name = "Another Service Overview"
# (4 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# honeycombio_board.overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "overview" {
id = "6E_cEMEDViGU"
name = "Service Overview"
# (4 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# honeycombio_board.query_only_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "query_only_overview" {
id = "wq_6sNVcYjMo"
name = "Query Only Board"
# (4 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# honeycombio_board.slo_only_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "slo_only_overview" {
id = "up_CzuDEizVS"
name = "SLO Only Board"
# (4 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# honeycombio_flexible_board.another_overview will be imported
# (config will be generated)
resource "honeycombio_flexible_board" "another_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/Aq_Sbk6dvknb"
description = "My second flexible board description"
id = "Aq_Sbk6dvknb"
name = "Another Service Overview"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 4
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.overview will be imported
# (config will be generated)
resource "honeycombio_flexible_board" "overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/6E_cEMEDViGU"
description = "My flexible board description"
id = "6E_cEMEDViGU"
name = "Service Overview"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 4
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.query_only_overview will be imported
# (config will be generated)
resource "honeycombio_flexible_board" "query_only_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/wq_6sNVcYjMo"
description = "My query onyl board description"
id = "wq_6sNVcYjMo"
name = "Query Only Board"
tags = {}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 0
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.slo_only_overview will be imported
# (config will be generated)
resource "honeycombio_flexible_board" "slo_only_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/up_CzuDEizVS"
description = "My slo only board description"
id = "up_CzuDEizVS"
name = "SLO Only Board"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
}
Plan: 4 to import, 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│ - honeycombio_board.overview
│ - honeycombio_board.slo_only_overview
│ - honeycombio_board.query_only_overview
│ - honeycombio_board.another_overview
│
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
╷
│ Warning: Config generation is experimental
│
│ Generating configuration during import is currently experimental, and the generated configuration format may change in future versions.
╵
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Terraform has generated configuration and written it to migrated.tf. Please review the configuration and edit it as necessary before adding it to version control.
Note: You didn't use the `-out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
terraform apply
to Ensure Proper Syncing Use the following terraform apply
command (and replace with your relevant variables):
HONEYCOMB_API_KEY=xxxx HONEYCOMB_API_ENDPOINT=http://localhost:8081 terraform apply
This command will:
honeycombio_board
resource from the state and prevent their deletionhoneycombio_flexible_board
resources to the state and enable themAfter running the command, the output for our example looks like:
honeycombio_flexible_board.another_overview: Preparing import... [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.query_only_overview: Preparing import... [id=wq_6sNVcYjMo]
honeycombio_flexible_board.slo_only_overview: Preparing import... [id=up_CzuDEizVS]
honeycombio_flexible_board.overview: Preparing import... [id=6E_cEMEDViGU]
honeycombio_flexible_board.another_overview: Refreshing state... [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.query_only_overview: Refreshing state... [id=wq_6sNVcYjMo]
honeycombio_flexible_board.overview: Refreshing state... [id=6E_cEMEDViGU]
honeycombio_flexible_board.slo_only_overview: Refreshing state... [id=up_CzuDEizVS]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
# honeycombio_board.another_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "another_overview" {
id = "Aq_Sbk6dvknb"
name = "Another Service Overview"
# (4 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# honeycombio_board.overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "overview" {
id = "6E_cEMEDViGU"
name = "Service Overview"
# (4 unchanged attributes hidden)
# (2 unchanged blocks hidden)
}
# honeycombio_board.query_only_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "query_only_overview" {
id = "wq_6sNVcYjMo"
name = "Query Only Board"
# (4 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# honeycombio_board.slo_only_overview will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
. resource "honeycombio_board" "slo_only_overview" {
id = "up_CzuDEizVS"
name = "SLO Only Board"
# (4 unchanged attributes hidden)
# (1 unchanged block hidden)
}
# honeycombio_flexible_board.another_overview will be imported
resource "honeycombio_flexible_board" "another_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/Aq_Sbk6dvknb"
description = "My second flexible board description"
id = "Aq_Sbk6dvknb"
name = "Another Service Overview"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 4
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.overview will be imported
resource "honeycombio_flexible_board" "overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/6E_cEMEDViGU"
description = "My flexible board description"
id = "6E_cEMEDViGU"
name = "Service Overview"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 4
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.query_only_overview will be imported
resource "honeycombio_flexible_board" "query_only_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/wq_6sNVcYjMo"
description = "My query onyl board description"
id = "wq_6sNVcYjMo"
name = "Query Only Board"
tags = {}
panel {
type = "query"
position {
height = 8
width = 4
x_coordinate = 0
y_coordinate = 0
}
query_panel {
query_annotation_id = "vk_iEUQtbsuM"
query_id = "pg_hHHnysmE3"
query_style = "combo"
}
}
}
# honeycombio_flexible_board.slo_only_overview will be imported
resource "honeycombio_flexible_board" "slo_only_overview" {
board_url = "http://localhost:8080/ronald-team/environments/prod-env/board/up_CzuDEizVS"
description = "My slo only board description"
id = "up_CzuDEizVS"
name = "SLO Only Board"
tags = {}
panel {
type = "slo"
position {
height = 4
width = 3
x_coordinate = 0
y_coordinate = 0
}
slo_panel {
slo_id = "gb_vu8cL6Sef"
}
}
}
Plan: 4 to import, 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│ - honeycombio_board.slo_only_overview
│ - honeycombio_board.another_overview
│ - honeycombio_board.overview
│ - honeycombio_board.query_only_overview
│
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
honeycombio_flexible_board.slo_only_overview: Importing... [id=up_CzuDEizVS]
honeycombio_flexible_board.slo_only_overview: Import complete [id=up_CzuDEizVS]
honeycombio_flexible_board.query_only_overview: Importing... [id=wq_6sNVcYjMo]
honeycombio_flexible_board.query_only_overview: Import complete [id=wq_6sNVcYjMo]
honeycombio_flexible_board.another_overview: Importing... [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.another_overview: Import complete [id=Aq_Sbk6dvknb]
honeycombio_flexible_board.overview: Importing... [id=6E_cEMEDViGU]
honeycombio_flexible_board.overview: Import complete [id=6E_cEMEDViGU]
Apply complete! Resources: 4 imported, 0 added, 0 changed, 0 destroyed.