Slack added a table block to Block Kit, and if you haven’t played with it yet, the initial reaction is usually one of two things: “finally” or “wait, that’s it?” Both reactions are valid. Here’s an honest look at what the table block actually does, where it shines, and where it falls short.
What the table block is
The rich_text_table is a block element that renders a grid of cells inside a rich_text block. Each cell can contain formatted text (bold, italic, links, code) using the same rich text element types as the rest of the rich_text block family.
A minimal example:
{
"type": "rich_text",
"elements": [
{
"type": "rich_text_table",
"columns": 3,
"border": 1,
"elements": [
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Service", "style": { "bold": true } }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Status", "style": { "bold": true } }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Latency", "style": { "bold": true } }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "API Gateway" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "✅ OK" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "42ms" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "Auth Service" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "🔴 Down" }] },
{ "type": "rich_text_section", "elements": [{ "type": "text", "text": "—" }] }
]
}
]
}
The columns field defines how many columns the table has. Slack infers rows from the total number of elements divided by columns. Elements fill left-to-right, top-to-bottom. There’s no separate header row: you style the first row’s cells as bold if you want it to look like a header.
What it can’t do
Before getting too excited, here are the real limitations:
No column width control. Slack determines column widths automatically. If one cell has a long string, the column expands. You can’t pin widths or force wrapping.
No cell merging. No colspan or rowspan. Every cell is a single unit.
No alignment control. You can’t right-align numbers. Everything is left-aligned.
No overflow handling. Long content doesn’t truncate: it wraps or pushes the column wider.
No interactive elements in cells. Buttons, select menus, and overflow menus can’t live inside table cells. Tables are display-only.
Rendering varies across clients. The table renders well in the Slack desktop and mobile apps. In email notifications and some third-party Slack clients, the table may render as plain text or not at all.
When to actually use it
Given those constraints, tables earn their place in specific scenarios:
Status summaries with consistent structure. A service health overview, deployment summary, or test results table are a natural fit. The structure is predictable, the content is short per cell, and the comparison across rows is the whole point.
Before/after comparisons. Two-column tables (“Before” and “After”) are readable and add genuine clarity for config changes, pricing updates, or migration summaries.
Scheduled digests with tabular data. A daily table of metrics (errors, latency, uptime per service) sent to an ops channel is a good use. The data is uniform, the column count is fixed, and people know to scan it.
Sprint or project status boards. A table with columns like “Feature | Owner | Status” is more readable than a bulleted list when there are 6+ items.
When not to use it
Anything with variable-length content. If one row could have a 10-word value and another could have 3 words in the same column, the table will look uneven and hard to read.
Data that needs number formatting or alignment. Currency, percentages, and counts look bad left-aligned without column width control.
Replacing a real dashboard. Tables in Slack are a snapshot, not an interactive view. If people need to sort, filter, or drill into the data, link to a dashboard instead of trying to replicate it in Slack.
High-cardinality data. A 20-row table in a Slack message is hard to read. If the table has more than ~8 rows, reconsider whether a link to a structured view is better.
Building tables without writing JSON
Writing table JSON by hand is tedious. The column count has to match the elements count exactly, every cell is its own object, and mistakes are hard to debug visually.
LithoBlocks handles the table block generation from your raw data. You build the table template visually (define the columns, configure the header row, set any formatting) and then fire your data payload to LithoBlocks via webhook. LithoBlocks compiles your data into the correct rich_text_table structure and sends the message to Slack. You never touch the nested JSON; your backend or automation just sends the data array it already has.
Stop building complex Block Kit table structures in your systems and automations. Define the template once in LithoBlocks, send your data, get the right Slack message. Try it free →