Email message tags and topics are both generally available. You can label any outgoing message with metadata you choose, and attribute it to a mailing list your recipients can leave on their own terms.
A tag is a name and a value you choose. There is no schema to define and nothing to configure first. A topic is the other half: a list you create once, that a recipient can unsubscribe from without losing anything else you send them.
Why email message tags matter
Without tags, your sending logs are one undifferentiated stream. Answering “how did last Tuesday’s invoice run actually deliver” means scrolling, or exporting and grouping by hand.
With them, that question is a filter. Tag by campaign, tenant, feature or environment, and the same label follows the message from the send call through to the delivery, open, click and bounce events. For anyone running multi-tenant sending, tagging by tenant turns a support question into a lookup.
Names run to 16 characters, values to 32, and you can attach up to 20 tags to a message. That is enough for the dimensions you actually query on, and small enough that nobody ends up storing a JSON blob in a tag value.
How to use them
Add a tags array and a topic to any send, over REST or SMTP:
{
"from": "billing@example.com",
"to": "customer@example.com",
"subject": "Your invoice",
"topic": "receipts",
"tags": [
{ "name": "tenant", "value": "acme" },
{ "name": "kind", "value": "invoice" }
]
}
Over SMTP the same two travel as X-Mailkube-Tags and X-Mailkube-Topic headers, so an application that already speaks SMTP gets both without code changes.
Then filter your logs by any tag, and read the tags straight back from your webhook payloads to route events without a lookup on your side.
A topic decides who receives it
Tags describe a message. They never change what happens to it. A topic can stop one, and that difference is the whole reason both exist.
Attribute a send to an opt-out topic and any recipient who unsubscribed from that topic is dropped before delivery. The send is still accepted and still counts against your quota, exactly as a suppressed hard bounce does, and you see it on the email.suppressed webhook rather than as a silent disappearance. Name a topic that does not exist or has been disabled and the send is rejected before anything is charged.
The part worth pausing on: an unsubscribe scopes to the topic, never to the account. Someone who leaves your product newsletter still gets their password reset and their receipts. Most platforms default to an account-wide suppression list, which quietly turns one marketing opt-out into a broken transactional pipeline. Recipients manage all of it themselves in the subscription center, one click included.
Both break down on the dashboard
Sends carrying a topic get their own panel, so you can see which lists are delivering and which are dragging.

Tags get a treemap. Each tile is one tag, sized by how much volume it carries and coloured by how much of that volume was accepted, so a small problem inside a large campaign is visible without running a query first.

One deliberate limitation worth knowing: tags are not exported as Prometheus labels. An open-ended set of values would blow up label cardinality on the metrics backend, so tags stay in the logs and the dashboard where high cardinality is fine.
Links
Full validation rules, limits and the webhook payload shape are in the tags documentation , and opt-in against opt-out behaviour is covered in the topics documentation . The release entry is in the changelog, and the reasoning behind this sending model is on the why page.