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. 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. 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. 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. 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. 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. 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.

Example inputmain.tf
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"
}
STACKIT Terraform by StackToITterraform/messaging.tf
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.

Review commentsterraform/messaging.tf
# 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 featureRabbitMQ approachDecision
QueueA RabbitMQ queue that you configure in the instanceQueue names and arguments, by the application team
Topic with subscriptionsAn exchange with a queue bound for each subscriberExchange type and bindings
Dead-letteringA dead-letter exchange set as a queue argumentWhich queues need one
Message lifetime, delivery limitQueue arguments; lock duration has no match, the nearest is the consumer_timeout parameterAccept the limit or build it into the consumer
SessionsNo session concept: consistent-hash exchanges or single-active consumersOrdering design per key
Duplicate detectionNo built-in deduplication: consumers must be idempotentIdempotency in the consumers
Subscription filter ruleNot assessed by this build; an architect decides the targetBinding keys, headers or a consumer-side filter
Namespace tierA RabbitMQ plan; a sizing decisionPlan 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.

Example inputmain.tf
resource "azurerm_servicebus_subscription_rule" "shipping_only" {
  name            = "eu-only"
  subscription_id = azurerm_servicebus_subscription.shipping.id
  filter_type     = "SqlFilter"
  sql_filter      = "region = 'EU'"
}
StackToIT assessmentassessment.json
{
  "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.