AZURE SERVICE BUS → STACKIT RABBITMQ
Azure Service Bus to STACKIT RabbitMQ
Service Bus moves to STACKIT RabbitMQ as a replatform: one RabbitMQ instance hosts the queues and exchanges, and clients switch from the Service Bus SDK to an AMQP 0-9-1 client. StackToIT writes the instance, lists every queue and topic setting it does not carry and names the Service Bus features that RabbitMQ handles differently.
The steps, in order
1. Inventory entities and features
List namespaces, queues, topics, subscriptions and their rules. For each, note sessions, duplicate detection, dead-lettering, message lifetime and delivery limits. These are the settings that decide how much code changes.
2. Assess the Terraform
The assessment turns each namespace, with its queues and topics, into one unit and tells you what the draft carries and what it does not.
3. Create the RabbitMQ instance
Set the project, the plan, the version and the clients allowed to connect. The access list replaces the default range, so you list your clients.
4. Set up the topology
Configure queues, exchanges and bindings in the instance, from the application or from deployment scripts (practice). The draft creates the instance only and lists each queue and topic setting as not carried.
5. Switch the clients
Producers and consumers move to an AMQP 0-9-1 client library, a new host, a TLS setting and the credentials of the instance.
6. Drain and cut over
Let consumers empty the Azure queues, point producers at RabbitMQ and keep the namespace until the last message is handled. This is practice, not a step the run plans for you.
A namespace with queues and a topic, converted
A small estate written for this page and assessed by StackToIT on 4 November 2026. Left: the Azure input. Right: the resource block of the STACKIT Terraform the engine wrote; the review comments above it in the file are left out here.
resource "azurerm_servicebus_namespace" "orders" {
name = "sb-orders-gwc"
location = azurerm_resource_group.msg.location
resource_group_name = azurerm_resource_group.msg.name
sku = "Premium"
capacity = 1
premium_messaging_partitions = 1
}
resource "azurerm_servicebus_queue" "invoices" {
name = "invoices"
namespace_id = azurerm_servicebus_namespace.orders.id
max_delivery_count = 5
lock_duration = "PT1M"
requires_duplicate_detection = true
dead_lettering_on_message_expiration = true
default_message_ttl = "P7D"
}
resource "azurerm_servicebus_queue" "sessions" {
name = "fulfilment-sessions"
namespace_id = azurerm_servicebus_namespace.orders.id
requires_session = true
max_delivery_count = 10
}
resource "azurerm_servicebus_topic" "events" {
name = "order-events"
namespace_id = azurerm_servicebus_namespace.orders.id
default_message_ttl = "P1D"
}resource "stackit_rabbitmq_instance" "messaging" {
project_id = var.project_id
name = "messaging"
plan_name = var.rabbitmq_plan_name
version = var.rabbitmq_version
parameters = {
sgw_acl = join(",", var.rabbitmq_allowed_cidrs)
}
}One instance for the whole namespace
The queues and the topic do not become Terraform resources. The namespace becomes one stackit_rabbitmq_instance; sku = Premium, capacity and the messaging partitions are listed as not carried, and the plan name and version are variables without a default.
The access list has no default
The variable for the allowed CIDRs rejects an empty list, because the STACKIT default range admits the addresses of every STACKIT customer, as the engine states.
The version needs a check
The variable text records that the service catalogue and STACKIT lifecycle page disagree on the offered RabbitMQ version, so no default is set. Confirm it against your region before any apply. As of November 2026 the lifecycle page lists 4.0 (released April 2025, end of life to be announced), 3.13 (end of life September 2025) and 3.10 (end of life March 2025). None of the STACKIT RabbitMQ pages opened for this guide names the protocols an instance accepts, so test your AMQP 0-9-1 or AMQP 1.0 client against a real instance.
What the draft says it does not carry
The lines the engine wrote above the instance for the namespace, the two queues and the topic, followed by the two feature warnings, as the file has them.
# NOT CARRIED (azurerm_servicebus_namespace.orders): capacity = 1, name = sb-orders-gwc, premium_messaging_partitions = 1, sku = Premium — configure its queues and topics as queues and exchanges in the RabbitMQ instance; none of the namespace's settings is generated.
# NOT CARRIED (azurerm_servicebus_queue.invoices): dead_lettering_on_message_expiration = true, default_message_ttl = P7D, lock_duration = PT1M, max_delivery_count = 5, name = invoices, namespace_id, requires_duplicate_detection = true — a setting of azurerm_servicebus_namespace.orders: configure its queues and topics as queues and exchanges in the RabbitMQ instance; none of the namespace's settings is generated.
# NOT CARRIED (azurerm_servicebus_queue.sessions): max_delivery_count = 10, name = fulfilment-sessions, namespace_id, requires_session = true — a setting of azurerm_servicebus_namespace.orders: configure its queues and topics as queues and exchanges in the RabbitMQ instance; none of the namespace's settings is generated.
# NOT CARRIED (azurerm_servicebus_topic.events): default_message_ttl = P1D, name = order-events, namespace_id — a setting of azurerm_servicebus_namespace.orders: configure its queues and topics as queues and exchanges in the RabbitMQ instance; none of the namespace's settings is generated.
# azurerm_servicebus_namespace.orders: WARNING sb-sessions: Queues use sessions (ordered, grouped processing); RabbitMQ has no session concept, so ordering per key needs consistent-hash exchanges or single-active consumers.
# azurerm_servicebus_namespace.orders: WARNING sb-duplicate-detection: Duplicate detection is enabled; RabbitMQ has no built-in deduplication, so consumers must be idempotent.Service Bus features and their RabbitMQ answers
Taken from the run and its reasons. The right column says who owns the decision.
| Service Bus feature | RabbitMQ approach | Decision |
|---|---|---|
| Queue | A RabbitMQ queue that you configure in the instance | Queue names and arguments, by the application team |
| Topic with subscriptions | An exchange with a queue bound for each subscriber | Exchange type and bindings |
| Dead-lettering | A dead-letter exchange set as a queue argument | Which queues need one |
| Message lifetime, delivery limit | Queue arguments; lock duration has no match, the nearest is the consumer_timeout parameter | Accept the limit or build it into the consumer |
| Sessions | No session concept: consistent-hash exchanges or single-active consumers | Ordering design per key |
| Duplicate detection | No built-in deduplication: consumers must be idempotent | Idempotency in the consumers |
| Subscription filter rule | Not assessed by this build; an architect decides the target | Binding keys, headers or a consumer-side filter |
| Namespace tier | A RabbitMQ plan; a sizing decision | Plan size, version, access list |
The sessions queue and the duplicate-detection setting in the example input produce the two warnings above; the run leaves each of these settings open for a person.
A resource this build does not assess
A subscription rule has no entry in the assessment catalogue of this build. The run records it as a manual unit with LOW confidence and writes nothing for it. Left: the input. Right: the assessment fields as the run wrote them.
resource "azurerm_servicebus_subscription_rule" "shipping_only" {
name = "eu-only"
subscription_id = azurerm_servicebus_subscription.shipping.id
filter_type = "SqlFilter"
sql_filter = "region = 'EU'"
}{
"id": "azurerm_servicebus_subscription_rule.shipping_only",
"result": {
"class": "MANUAL_REVIEW",
"confidence": "LOW",
"reason": "azurerm_servicebus_subscription_rule is not in the knowledge base catalogue; an architect has to decide the target. Nothing of this resource is assessed or drafted (unknown source type).",
"coverage": "UNKNOWN_SOURCE_TYPE"
}
}It still needs an owner
The manual-steps file lists the rule under steps with no owner role, because the assessment gives the unit no category. Assign one yourself.
Read the filter, not just the name
The SQL filter selects which messages a subscription receives. On RabbitMQ that logic moves into bindings or into the consumer.
Decisions the architect owns
Plan, version and access list
The run asks for a RabbitMQ plan, a version and the client CIDRs. None has a default.
Ordering and duplicates
If any queue requires sessions or duplicate detection, the application design changes. Decide it before the first message moves.
In-flight messages
The data-movement file for this run is marked not applicable: the source holds no database, cache or object store, and a queue or topic service is not read as stateful. Messages in flight are yours to drain.
Backups and recovery
STACKIT documents automatic backups of the RabbitMQ service: a full backup every 4 hours, kept for 14 days. Check whether that fits your recovery needs.
Plugins you may need
The documentation lists plugins you can enable through the parameter file, among them consistent hash exchange, shovel and federation.
Questions about this migration
Can the same client library connect to both brokers?
Not the Service Bus SDK as it is. Microsoft names AMQP 1.0 as the primary Service Bus protocol and says it lets you write applications that work against Service Bus and brokers such as RabbitMQ. The run plans a switch to an AMQP 0-9-1 client. Which route works depends on the RabbitMQ version offered in your region and the Service Bus features your code uses, so test it against the instance.
Does StackToIT create the queues and exchanges?
No. The draft creates one RabbitMQ instance. You configure queues and exchanges in it, and each queue name and setting appears as a not-carried note.
How do I replace sessions?
RabbitMQ has no session concept. The run points to consistent-hash exchanges or single-active consumers for ordering per key, and both need a design decision.
What happens to the messages still in the queues?
The tool moves no data. Drain the Azure queues with the existing consumers, or republish deliberately, and keep the namespace until the last message is handled.
Sources
Your next move: STACKIT.
Tell us about your estate. We show you what StackToIT delivers for it: target architecture, Terraform artifacts and a structured migration plan.