Messaging and Integration Services

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

See the section bibliography for the reference material consulted while preparing these pages.

Commands below target Azure CLI 2.90.0 (checked 2026-09-27); re-verify flags with az servicebus --help, az eventgrid --help, az eventhubs --help, az storage queue --help, az logic --help and az webpubsub --help before relying on them, since the messaging command groups add flags (particularly around passwordless auth and geo-replication) fairly often.

This page covers the services Bookshelf reaches for when one part of the system needs to hand work or a notification to another part without a direct, synchronous call: Service Bus for durable point-to-point and publish/subscribe messaging with delivery guarantees, Event Grid for reacting to discrete state-change events (both Azure’s own and custom application events), Event Hubs for high-throughput event streaming (including its Kafka-compatible endpoint), Storage Queues as a simpler, cheaper alternative to Service Bus queues, Logic Apps for low-code workflow orchestration across connectors, and Web PubSub/SignalR Service for pushing real-time updates to connected clients. It ends with a comparison to help decide which of these to reach for in a given scenario. Generic messaging concepts — delivery guarantees, competing consumers, the publish/subscribe pattern, transactional outbox and idempotent-consumer patterns — are covered in depth in the sibling Messaging Reference, in particular Messaging Protocols for wire-protocol details (including how AMQP 0-9-1/1.0 relate to what Service Bus and Event Hubs actually speak on the wire); this page stays focused on the Azure service layer — provisioning, passwordless auth, and which service fits which shape of problem — rather than repeating that material.

Service Bus

Azure Service Bus is a fully managed enterprise message broker offering queues (point-to-point, one consumer processes each message) and topics with subscriptions (publish/subscribe, each subscription gets its own copy of every message it’s subscribed to, optionally filtered by a SQL-like or correlation filter). Both entity types support a dead-letter queue (DLQ) — a side channel every queue and subscription carries automatically, where messages land after exceeding MaxDeliveryCount, expiring past their time-to-live, or being explicitly dead-lettered by the receiver — and sessions, which group related messages (for example, all messages for one order) so a single receiver processes them in order and can hold session-scoped state between messages. The Standard tier is a fully multi-tenant, pay-per-operation service; the Premium tier runs on dedicated messaging units for predictable latency and throughput, and is required for larger message sizes and some geo-replication features.

In the Azure portal

  1. Search for Service Bus and select Create.

  2. On Basics, choose $RG, $LOCATION, a namespace name, and a Pricing tier (Standard is enough for most workloads; pick Premium for guaranteed throughput or larger messages).

  3. Once the namespace is created, use + Queue or + Topic on its Entities blade to add queues and topics; adding a subscription happens from inside a topic’s own blade.

  4. On a queue’s or subscription’s Dead-letter tab, review dead-lettered messages, or resubmit them back onto the originating queue/topic once the underlying problem is fixed.

  5. Under Access control (IAM), assign the Azure Service Bus Data Owner, Data Sender, or Data Receiver role to the managed identities or service principals that need Entra-based, passwordless access, instead of copying a shared access key from Shared access policies.

With the Azure CLI

export RG=rg-bookshelf
export LOCATION=eastus2

az group create --name "$RG" --location "$LOCATION"

az servicebus namespace create \
  --name sb-bookshelf \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --sku Standard \
  --disable-local-auth true

az servicebus queue create \
  --namespace-name sb-bookshelf \
  --resource-group "$RG" \
  --name orders-queue \
  --enable-session true \
  --enable-dead-lettering-on-message-expiration true \
  --max-delivery-count 10 \
  --lock-duration PT1M

az servicebus topic create \
  --namespace-name sb-bookshelf \
  --resource-group "$RG" \
  --name order-events

az servicebus topic subscription create \
  --namespace-name sb-bookshelf \
  --resource-group "$RG" \
  --topic-name order-events \
  --name shipping-subscription \
  --enable-dead-lettering-on-message-expiration true \
  --max-delivery-count 10

--disable-local-auth true on the namespace turns off SAS key authentication entirely, so every client must authenticate with Microsoft Entra ID; grant the roles named above with az role assignment create (see Identity and Access) rather than distributing a connection string. --enable-session on the queue turns on session support (a producer sets SessionId on each message that belongs together); --enable-dead-lettering-on-message-expiration and --max-delivery-count are what make the DLQ described above actually populate for this entity, as opposed to only reacting to explicit dead-lettering calls from the receiver. See az servicebus namespace command reference, az servicebus queue command reference, and az servicebus topic command reference.

Passwordless access from Spring Boot

Spring Cloud Azure’s Service Bus starter and the Spring Cloud Stream Service Bus binder both authenticate with DefaultAzureCredential out of the box once local auth is disabled — no connection string in configuration:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-servicebus</artifactId>
</dependency>
spring:
  cloud:
    azure:
      servicebus:
        namespace: sb-bookshelf
        credential:
          managed-identity-enabled: true
          client-id: <user-assigned-managed-identity-client-id>   # omit for system-assigned identity

@JmsListener/ServiceBusTemplate (imperative) or the Spring Cloud Stream Service Bus binder (functional, spring-cloud-azure-stream-binder-servicebus, configuring a StreamBridge/@Bean Function<…​> per queue or topic subscription instead of an explicit template) both pick up this same spring.cloud.azure.servicebus.* block; neither needs a connection-string property once the namespace only accepts Entra ID. See Spring Cloud Azure — Service Bus support and Service Bus authentication and authorization.

Event Grid

Event Grid is a publish/subscribe eventing service for reacting to discrete state-change events — "a blob was created", "a resource was deleted", "an order was placed" — rather than carrying the payload of ongoing work the way Service Bus or Event Hubs do. A system topic is a built-in event source Azure itself manages for a resource type already in the subscription — most commonly a Storage account’s Blob Storage events (Microsoft.Storage.BlobCreated, BlobDeleted, and the rest), but also Resource Groups, Key Vault, Container Registry and others — and needs no publishing code: the resource emits events, Event Grid routes them. A custom topic is one an application creates and publishes its own domain events to explicitly (an HTTP POST of a CloudEvents- or Event Grid-schema payload), for events with no built-in Azure source. Either kind of topic gets one or more event subscriptions, each naming a handler (a webhook, an Azure Function, a Service Bus queue/topic, an Event Hubs namespace, or a Storage Queue) and, optionally, a filter narrowing which event types or subjects that handler receives.

In the Azure portal

  1. For a system topic: open the source resource (for example a storage account) and, on its Events blade, select + Event Subscription directly — the portal creates the underlying system topic automatically the first time.

  2. For a custom topic: search for Event Grid Topics, select Create, and choose $RG, $LOCATION, a topic name, and either the Event Grid schema or Cloud Event schema v1.0.

  3. On either topic, + Event Subscription opens the subscription wizard: name it, pick an Endpoint type (webhook, Event Hubs, Service Bus queue/topic, Storage Queue, or Azure Function), and optionally add a Filters rule on event type or subject prefix/suffix.

With the Azure CLI

# System topic on an existing storage account's Blob Storage "blob created" events
az eventgrid system-topic create \
  --name egst-bookshelf-blobs \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --topic-type microsoft.storage.storageaccounts \
  --source "$(az storage account show --name stbookshelf --resource-group "$RG" --query id -o tsv)"

az eventgrid system-topic event-subscription create \
  --name blob-created-to-servicebus \
  --resource-group "$RG" \
  --system-topic-name egst-bookshelf-blobs \
  --included-event-types Microsoft.Storage.BlobCreated \
  --endpoint-type servicebusqueue \
  --endpoint "$(az servicebus queue show --namespace-name sb-bookshelf --resource-group "$RG" --name orders-queue --query id -o tsv)"

# Custom topic for application-defined domain events
az eventgrid topic create \
  --name egt-bookshelf-domain \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --input-schema cloudeventschemav1_0

az eventgrid event-subscription create \
  --name domain-events-to-webhook \
  --source-resource-id "$(az eventgrid topic show --name egt-bookshelf-domain --resource-group "$RG" --query id -o tsv)" \
  --endpoint-type webhook \
  --endpoint "https://api.bookshelf.example/webhooks/order-events"

--endpoint-type servicebusqueue (or servicebustopic, eventhub, storagequeue, azurefunction) points an Event Grid subscription at any of the other services on this page, which is how a Blob Storage upload can trigger a Service Bus message without any glue code. Both custom-topic publishing and system-topic subscription management authenticate with Microsoft Entra ID via role assignments (EventGrid Data Sender to publish, EventGrid EventSubscription Contributor to manage subscriptions) rather than the topic’s access key. See Event Grid overview, System topics, and az eventgrid system-topic command reference.

Event Hubs

Event Hubs is a high-throughput event streaming service — a managed, partitioned, append-only log conceptually close to Apache Kafka — built for ingesting large volumes of telemetry or activity events (clickstreams, IoT readings, application logs) that downstream consumers replay from an offset rather than receive one-shot the way Service Bus messages are consumed. Its distinguishing feature for teams already invested in Kafka tooling is the Kafka-compatible endpoint: an event hub is addressable as a Kafka topic over the Kafka wire protocol on port 9093, so an existing Kafka producer/consumer, kafkacat, Kafka Connect connector, or Kafka Streams application can often point at it by changing only bootstrap.servers and the SASL configuration, without touching application code, provided it targets a Standard, Premium, or Dedicated tier namespace (the Kafka endpoint isn’t available on Basic).

In the Azure portal

  1. Search for Event Hubs, select Create, and choose $RG, $LOCATION, a namespace name, and a Pricing tier of Standard or higher (required for the Kafka endpoint).

  2. On the namespace’s Event Hubs blade, + Event Hub creates an event hub (the Kafka-side "topic") with a chosen partition count and message retention.

  3. Under Access control (IAM), assign Azure Event Hubs Data Owner/Data Sender/Data Receiver to the identities that will produce or consume, whether they connect over AMQP or the Kafka endpoint.

With the Azure CLI

az eventhubs namespace create \
  --name ehns-bookshelf \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --sku Standard \
  --disable-local-auth true

az eventhubs eventhub create \
  --namespace-name ehns-bookshelf \
  --resource-group "$RG" \
  --name order-activity \
  --partition-count 4 \
  --retention-time-in-hours 24

A Kafka client authenticates against this endpoint with security.protocol=SASL_SSL and sasl.mechanism=OAUTHBEARER, obtaining its token from Microsoft Entra ID the same DefaultAzureCredential way as any other Azure SDK client (a callback handler exchanges the credential’s token for the OAUTHBEARER value Kafka’s SASL layer expects), rather than the PLAIN/connection-string mechanism Event Hubs also still accepts for compatibility. bootstrap.servers becomes ehns-bookshelf.servicebus.windows.net:9093 and the event hub name (order-activity) is used as the Kafka topic name; Kafka’s own topic-creation semantics don’t apply since the event hub itself has to be created ahead of time. See Apache Kafka protocol support in Azure Event Hubs and az eventhubs eventhub command reference.

Storage Queues, briefly

Azure Storage Queues (part of a general-purpose storage account, alongside Blob/Table/File) are a much simpler message queue: a message is up to 64 KB, addressed by a plain HTTP(S) URL under the storage account, with no sessions, no topics/subscriptions, and no dead-letter queue as a first-class construct (an application has to build its own poison-message handling by tracking a message’s DequeueCount and moving it to a separate queue itself). What Storage Queues trade for that simplicity is cost and scale: they’re billed as ordinary storage transactions rather than a dedicated messaging SKU, a single queue can hold millions of messages up to the storage account’s overall capacity, and there’s no namespace/tier to provision beyond the storage account already used for Blob Storage. Reach for a Storage Queue over a Service Bus queue for a plain work backlog (the Web-Queue-Worker pattern) that doesn’t need ordering guarantees, sessions, or a managed DLQ, especially when a storage account already exists for other reasons.

az storage queue create \
  --name thumbnail-jobs \
  --account-name stbookshelf \
  --auth-mode login

--auth-mode login authenticates the CLI call itself with the signed-in identity’s Entra credentials instead of an account key; an application does the same by pointing the Storage Queues SDK’s QueueServiceClient at DefaultAzureCredential rather than a connection string, with Storage Queue Data Contributor (or …​Message Processor/…​Message Sender for narrower access) granted on the storage account. See Introduction to Azure Queue Storage and az storage queue command reference.

Logic Apps, briefly

Azure Logic Apps is a low-code workflow service: a designer-built (or JSON-defined) sequence of a trigger followed by actions drawn from 1,400+ prebuilt connectors, well suited to wiring together the other services on this page (poll a queue, call an API, branch on a condition, send an email) without writing an integration service from scratch. It comes in two hosting shapes that matter for cost and networking, not workflow authoring: the Consumption plan runs each logic app resource as a single workflow in multi-tenant, shared infrastructure and bills per action execution, which is the cheapest way to start and needs no capacity planning; the Standard plan runs on a dedicated App Service-based plan, hosts multiple workflows per logic app resource, supports direct VNet integration and private endpoints, and bills for the underlying plan’s compute rather than per execution, which suits higher-throughput or network-isolated workflows. Both plans deliver "at least once" — an application that can’t tolerate a duplicate action needs to make that action idempotent itself.

# Consumption logic app, defined inline from a workflow JSON definition file
az logic workflow create \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --name la-order-notifications \
  --definition workflow-definition.json

There’s no CLI command group for Standard logic apps (they’re deployed as a Function-app-shaped resource via Bicep/ARM or the Azure Functions Core Tools instead); the Consumption az logic workflow group above covers only the multi-tenant plan. See What is Azure Logic Apps? and az logic workflow command reference.

Web PubSub and SignalR Service, briefly

Both are managed services for pushing real-time updates to connected clients over WebSockets (falling back to other transports), so applications don’t have to operate their own long-lived-connection infrastructure or scale-out backplane. Azure SignalR Service is the managed backend for ASP.NET’s own SignalR programming model — hubs, Clients.All/Group/User, strongly-typed hubs — covered for ASP.NET Core in SignalR and for the OWIN-hosted SignalR 2 in SignalR 2; using it means changing the app’s SignalR configuration to point at the Azure service instead of running a self-hosted backplane, without changing hub code. Azure Web PubSub is the protocol-agnostic sibling: a lower-level connection/group/user model over plain WebSockets and a REST API, aimed at applications not already built on the SignalR hub abstraction (a non-.NET backend, a custom client protocol, or a Socket.IO/MQTT-based client) that still need the same broadcast/group/user delivery patterns and managed scale. Choosing between the two is really "does this application already speak SignalR’s hub protocol" — if it does (or is a new ASP.NET Core project), stay on SignalR Service and the pages linked above; otherwise Web PubSub is the more general fit.

az webpubsub create \
  --name wps-bookshelf \
  --resource-group "$RG" \
  --location "$LOCATION" \
  --sku Free_F1

Choosing between them

The services above sit on a spectrum from commands (tell one specific consumer to do one specific thing, reliably and in order) through events (announce that something happened, let zero or more interested parties react) to streams (a durable, replayable log of many events, read at each consumer’s own pace) and push (shove data straight at connected clients rather than another backend service):

Service Model Reach for it when Avoid it when

Service Bus

Commands / point-to-point + pub/sub

A specific unit of work must reach exactly one consumer reliably, in order, possibly grouped into a session, with a first-class dead-letter queue for poison messages

Many independent consumers need to replay the same event stream at their own pace (use Event Hubs), or the message is a plain, low-value backlog item with no ordering needs (Storage Queues are cheaper)

Event Grid

Events (push/pull, pub/sub)

Reacting to a discrete Azure resource state change (blob created, resource deleted) or a custom domain event, routing it to one or more handlers, often fanning out into Service Bus, Event Hubs, a Storage Queue, or a webhook

The payload itself is the work item to process end-to-end (Service Bus/Storage Queues), or the data is a continuous, high-volume stream to be replayed by multiple readers (Event Hubs)

Event Hubs

Streams (partitioned log, replay by offset)

Ingesting a high-throughput stream of telemetry/activity events that several independent consumer groups each need to read at their own offset, or the team already has Kafka producers/consumers/tooling to point at a managed endpoint

The unit of work needs guaranteed single-consumer delivery with sessions/DLQ semantics (Service Bus), or volume is low enough that the operational simplicity of Storage Queues or Service Bus is worth more than stream semantics

Storage Queues

Commands / point-to-point, simplified

A plain work backlog (Web-Queue-Worker) with no ordering, session, or first-class DLQ requirement, especially alongside a storage account already used for other things, where cost matters more than messaging features

The application needs sessions, a managed dead-letter queue, or topic/subscription fan-out (Service Bus)

Logic Apps

Orchestration across connectors

Wiring several of the above (and 1,400+ other systems) together with low-code branching/looping logic instead of writing and operating a bespoke integration service

The logic is performance-critical, needs full programming-language control, or is simple enough that a Service Bus consumer plus application code is less overhead than a workflow definition

Web PubSub / SignalR Service

Push to connected clients

Updates must reach browser/mobile clients holding an open connection in real time (dashboards, chat, live game state), rather than reaching another backend service

The receivers are backend services, not end-user client connections — any of the broker services above fits that better

flowchart TD Start["What needs to receive this?"] Client{"A connected end-user\nclient (browser/mobile)?"} OneConsumer{"Exactly one consumer,\nordering/sessions/DLQ needed?"} Cheap{"Simple backlog,\ncost over features?"} Stream{"Many consumers replay\na high-volume stream\n(Kafka-compatible)?"} Orchestrate{"Wiring many systems\nwith low-code branching?"} Start --> Client Client -- Yes --> PubSub["Web PubSub / SignalR Service"] Client -- No --> OneConsumer OneConsumer -- Yes --> Cheap Cheap -- Yes --> StorageQ["Storage Queues"] Cheap -- No --> ServiceBus["Service Bus queue/topic"] OneConsumer -- No --> Stream Stream -- Yes --> EventHubs["Event Hubs\n(Kafka-compatible endpoint)"] Stream -- No --> Orchestrate Orchestrate -- Yes --> LogicApps["Logic Apps"] Orchestrate -- "No, just react to\na discrete state change" --> EventGrid["Event Grid"]

Clean up

# Remove every resource created on this page (Service Bus namespace, Event Grid topics/subscriptions, Event
# Hubs namespace, Web PubSub instance, Logic App, and the resource group itself)
az group delete --name "$RG" --yes --no-wait

A Storage Queue created inside an existing storage account used for other purposes is removed on its own instead of deleting the whole account: az storage queue delete --name thumbnail-jobs --account-name stbookshelf --auth-mode login.

References