Service Bus: Queues, Topics and Access¶
The Integration Platform offers Azure Service Bus as a shared messaging service. You do not create a namespace of your own. You describe the queues, topics and subscriptions your workload needs in JSON files, open a pull request, and the platform creates them and the Entra ID groups that control who can send and receive. This page is for workload teams. Operators: see Service Bus automation (platform side).
Optional offering, set per platform
Whether the Service Bus shared service is available, in which environments and with which options, depends on your platform. Names, defaults and group patterns on this page are the usual values of the reference design. Ask your platform team.
How it works¶
Three layers work together (ADR-012):
| Layer | What it does | Who runs it |
|---|---|---|
| Shared service | The Service Bus namespace (Premium) and its networking. No entities. | Platform team |
| Spoke extension | Gives your spoke the rights it needs on the namespace when the spoke is deployed (Spoke extensions) | Platform team, with the spoke deployment |
| Service Bus automation | Creates your queues, topics and subscriptions from JSON files, and the access groups per entity | Integration platform engineers, from your pull requests |
flowchart LR
json["queues.json, topics.json,<br/>workload.json<br/>(your pull request)"] --> auto["Service Bus automation"]
auto -->|"creates"| ent["Queues, topics,<br/>subscriptions"]
auto -->|"creates"| grp["Entra ID groups<br/>per entity and role"]
grp -->|"role assignment"| ent
you["Your team"] -->|"adds managed identities<br/>to the groups"| grp
app["Logic App, Function App,<br/>Container App"] -->|"Entra ID, private endpoint"| ent
The namespace is reachable only through a private endpoint. Connect with Entra ID, not with connection strings or keys.
Define queues¶
Create a file called exactly queues.json anywhere under your configuration folder. A file holds one queue object or a
list of queue objects. Keep the file name: the automation collects every queues.json (and topics.json) in the
folder and all subfolders, so you can organise folders per workload, domain or environment. Duplicate definitions of the
same queue in different folders must be avoided.
{
"workload": "orders",
"name": "intake",
"max_delivery_count": 10
}
| Field | Required | Default | Meaning |
|---|---|---|---|
workload |
yes | The workload that owns the queue. Must match a workload definition (see below). | |
name |
yes | Queue name. The queue in Azure is called sbq-<workload>-<name>. |
|
max_delivery_count |
no | 10 | Deliveries before a message goes to the dead-letter queue |
lock_duration |
no | PT1M |
Lock time while a receiver processes a message (ISO 8601 duration) |
max_size_in_megabytes |
no | 1024 | Queue size |
requires_session |
no | false | Session-aware queue |
requires_duplicate_detection |
no | false | Duplicate detection, with duplicate_detection_history_time_window (default PT10M) |
dead_lettering_on_message_expiration |
no | false | Move expired messages to the dead-letter queue |
forward_dead_lettered_messages_to |
no | none | Forward dead-lettered messages to another entity |
default_message_ttl, auto_delete_on_idle, max_message_size_in_kilobytes, partitioning_enabled, express_enabled, batched_operations_enabled, status |
no | see the module | More Service Bus properties, passed through |
Define topics, subscriptions and rules¶
A topic is owned by the workload that publishes. Each subscription names the workload that consumes.
{
"workload": "orders",
"name": "order-created",
"subscriptions": [
{
"workload": "billing",
"name": "billing",
"rules": [
{
"name": "only-eu",
"filter_type": "SqlFilter",
"sql_filter": "region = 'EU'"
}
]
}
]
}
| Field | Notes |
|---|---|
| Topic fields | workload, name, support_ordering (default false), requires_duplicate_detection, max_size_in_megabytes (default 1024), and the same pass-through properties as queues |
| Subscription fields | workload, name, max_delivery_count (default 10), dead_lettering_on_filter_evaluation_error (default true), lock_duration (default PT1M), requires_session, and more |
| Rules | name and filter_type. SqlFilter takes sql_filter. CorrelationFilter takes a correlation_filter object (correlation_id, label, message_id, to, reply_to, session_id, content_type, properties). An optional action. |
Names in Azure: topic sbt-<workload>-<name>, subscription sbts-<subscription workload>-<subscription name>.
A queue per subscription (default)¶
For every subscription the automation also creates a queue named sbq-<subscription workload>-<topic name>-<subscription name>
and forwards the subscription to it. You listen to that queue, not to the subscription. This is
ADR-008. It gives you:
- dead-lettering on a queue that only your workload owns;
- a retry of a failed message without sending it again to the topic, so other subscribers do not receive it twice;
- a simpler model: you only need to know how to read from a queue.
The queue inherits its size and duplicate-detection settings from the topic. The behaviour is a switch of the automation
(auto_generate_queue_for_topic_subscription, default true). If the platform team turned it off, receivers read from the
subscription instead.
Define the workload¶
Each workload that appears in a file needs a workload definition (workload.json) with the name and the identities of its spoke, so the
automation knows whose service principal and groups to use. Ask your platform team who maintains this file and where it lives. The fields the automation reads are name, service_principal_object_id, owner_group_id,
contributor_group_id and reader_group_id. If a workload is used in a queue or topic but has no definition, the plan fails.
Who can do what: groups¶
For each entity the automation creates Entra ID groups in the administrative unit of the platform. Your team is owner of the groups (through the service principal of your spoke) and manages the membership.
| Group | Created for | Role it gets | Members at creation |
|---|---|---|---|
| Sender group | Every queue and every topic | Azure Service Bus Data Sender on that entity |
Empty. You add managed identities and service principals. |
| Receiver group | Every queue, and every subscription that is not forwarded to a queue | Azure Service Bus Data Receiver on that entity |
Empty. You add identities. |
| Operators group | Once per workload | Sender and receiver rights on every entity of the workload, for support actions such as resubmitting a failed message by hand | Owners and Contributors groups of your workload spoke |
The names follow a pattern that the platform team sets, with {workload} and {entity} as placeholders. The reference
pattern is integration-workload-{workload}-{entity}-sender and ...-receiver, where the entity is the Azure name of
the queue or topic, for example sbq-orders-intake. Ask your platform team for the pattern on your platform.
The Readers group of your spoke is also added to the platform's read-only group for the namespace, so readers can see the namespace in the portal.
Give an application access¶
- Find the group for the entity and role (for example the sender group of
sbq-orders-intake). Your platform team can give you the object IDs (the automation outputs them per workload). - Add the managed identity of your Logic App, Function App or Container App to the group in Microsoft Entra ID.
- Wait a few minutes. A group change takes a short time to take effect at the namespace.
- Connect with the namespace host name (
<namespace>.servicebus.windows.net) and Entra ID authentication.
You do not need a pull request for this. That is the point of the group model (ADR-005). You do need a firewall rule if the sender is outside your spoke or the traffic is not already allowed (Firewall rules and IP groups).
Do not add identities to the entity roles in the portal
Give access through the groups. A role assignment that someone adds directly on a queue is not part of the code, and the next deployment may remove it or leave a state nobody can review.
Change or remove entities¶
Change the JSON and open a pull request. Read the plan of the pull request for what happens.
- Most properties change in place.
- Removing a queue, topic or subscription removes its groups as well, and deletes the messages in it.
- Changing a name creates a new entity and removes the old one.
- Partitioning of a running namespace is a change with data impact. Ask the platform team first.
How the pull request becomes a change: Request and change.
Operating notes for workload teams¶
| Topic | What to know |
|---|---|
| Availability | The Premium namespace is zone-redundant by default. Geo-disaster recovery is an optional measure of the platform (Availability). |
| Throughput | Messaging units are scaled manually by the platform team. Scaling can reset connections briefly, so retry in your client. |
| Dead letters | Watch dead-letter growth on your queues. Alerting on the namespace is the platform's. Alerts on your application are yours. |
| Sharing | Several workloads share one namespace. Entity-level groups keep them apart: your group does not give access to the queue of another workload. |