Microsoft established September 30, 2026 as the retirement date for the named legacy Azure Service Bus SDK libraries and as the cutoff for Service Bus Messaging Protocol (SBMP) workloads. Organizations that have not completed the migration need evidence that every active sender and consumer uses a supported client and transport. After the cutoff, any remaining SBMP dependency becomes a production-remediation issue rather than an ordinary upgrade task.
The retirement creates two different risks. The WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus, and legacy Java com.microsoft.azure.servicebus libraries lose official support and updates, although an old binary might still start. SBMP is different: Microsoft states that workloads cannot use the protocol after September 30, 2026. A technically executable binary is therefore not evidence of a viable transport. Microsoft’s Azure Service Bus retirement documentation makes that distinction explicit.
This runbook works backward from production proof. It builds a verified estate, assigns every namespace and entity to an owner, freezes message contracts and delivery semantics, maps .NET and Java behavior to supported clients, isolates identity and network changes, tests failure windows, rehearses coexistence safely, deploys by risk ring, and ends with an auditable zero-legacy evidence package. The test is not merely whether the new client connects; it is whether every end-to-end workflow still produces the same business result under retries, lock loss, restarts, poison messages, and uncertain settlement acknowledgements.
Define the Exact Retirement Scope and the Failure Modes It Creates
The first control is a scope statement that procurement, engineering, security, and site reliability engineers (SREs) interpret the same way. The retirement notice does not retire the Azure Service Bus service. Microsoft established September 30, 2026 as the point at which the named legacy software development kits (SDKs) leave official support and SBMP becomes unavailable. Current JavaScript/TypeScript, Python, and Go Azure SDKs are not named in the notice, although their applications still belong in the inventory.
Item | Status from September 30, 2026 | Required action |
WindowsAzure.ServiceBus | Retired and unsupported | Replace it; isolate and migrate any post-cutoff discovery. |
Microsoft.Azure.ServiceBus | Retired and unsupported | Move to Azure.Messaging.ServiceBus and prove semantic parity. |
Legacy Java com.microsoft.azure.servicebus / com.microsoft.azure:azure-servicebus | Retired and unsupported | Move to com.azure:azure-messaging-servicebus and test Java behavior. |
SBMP transport | Unavailable after the cutoff | Eliminate by the cutoff; isolate any later dependency. |
JavaScript, Python, and Go SDKs not named in the notice | Outside this library retirement | Validate version, transport, ownership, identity, network, and wrappers. |
An overlooked SBMP process cannot send or receive after the cutoff. A legacy library using AMQP may continue to execute but is unsupported. A modern client can connect while changed auto-completion, concurrency, batching, retries, lock renewal, session handling, or shutdown creates duplicates, reordering, dead-letter queue growth, or a silent backlog.
Treat unexplained SBMP telemetry, an unknown binary owner, unavailable source, or an unexecuted workload as open risk. The discipline described in Refonte Learning’s guide to controlled API deprecation and versioning applies, but no rollback at or after September 30, 2026 may reinstate SBMP.
Promotion requires every workload to have a target, semantic baseline, test result, and supported AMQP-capable rollback. Unexplained SBMP or an irreconcilable business result blocks promotion. Recovery returns to a supported AMQP build or pauses intake while operators drain, reconcile, and replay.
Inventory Every Legacy Package, Protocol, Framework, and Hidden Consumer
Repository search is only one evidence stream. Service Bus clients can hide in shared libraries, Azure Functions extensions, WebJobs bindings, Logic Apps, Power Automate flows, integration platforms, scheduled tasks, desktop software, vendor binaries, framework starters, or images built months ago. A survey of serverless APIs and Azure Functions triggers explains the architectural setting; this retirement requires a deeper deployment-by-deployment inventory.
Use one authoritative record per deployable process or managed integration. At minimum, capture the following schema:
Field group | Required fields |
Software identity | Repository or binary, language, runtime, package and exact version, direct or transitive dependency, process/framework/connector, artifact hash |
Hosting and Azure scope | Host platform, Azure subscription, resource group, namespace, queue/topic/subscription, region |
Messaging behavior | Producer/consumer role, session or transaction use, protocol/transport configuration, authentication method, network path |
Ownership and risk | Technical owner, business owner, business criticality, message volume, peak rate, deployment frequency |
Evidence and plan | Last observed traffic, source availability, migration status, test status, exception owner, exception expiry |
Do not combine several binaries under “order platform” when they deploy independently. A command-line reconciler, web application, and overnight scheduler can reference the same namespace but differ in package, identity, transport, and execution frequency.
Find Compile-Time Dependencies Across .NET and Java Estates
For .NET, scan solution and project files, packages.config, PackageReference entries, packages.lock.json, Directory.Packages.props, generated .deps.json files, publish directories, NuGet caches, software bills of materials, and container layers. Resolve transitive packages rather than searching only source text. A practical first pass is:
dotnet list Commerce.sln package --include-transitive
grep -RInE 'WindowsAzure\.ServiceBus|Microsoft\.Azure\.ServiceBus' .
For Java, inspect Maven pom.xml files, Gradle build files and version catalogs, dependency-lock files, Spring or integration starters, shaded or “fat” JAR contents, application-server libraries, artifact repositories, and container layers. Generate resolved trees, because a parent platform or adapter can pull the legacy artifact indirectly:
mvn dependency:tree -Dincludes=com.microsoft.azure:azure-servicebus
./gradlew dependencies
grep -RInE 'com\.microsoft\.azure\.servicebus|azure-servicebus' .
Also search configuration and infrastructure as code for namespace hostnames, connection-string keys, transport settings, Service Bus trigger declarations, deployment slots, and old secret names. Compare source findings with the actual artifact deployed in each environment; a clean main branch does not prove that a long-lived virtual machine or desktop installation is clean.
When source is unavailable, record the binary hash, vendor, version, deployment location, namespace access, observed traffic, and contract owner. Inspect package manifests and runtime dependencies where legally and technically permitted, then obtain dated vendor evidence for SDK and protocol. Until the binary is upgraded, isolated, replaced, or disabled, mark it unavailable source: open risk.
Use Runtime Telemetry to Prove Where SBMP Still Exists
Azure Monitor’s AZMSApplicationMetricLogs resource-specific table includes fields such as NamespaceName, EntityName, OperationName, Outcome, AuthType, and Protocol; documented protocol values include AMQP and SBMP. Enable the relevant diagnostics on every in-scope namespace, route them to a controlled Log Analytics workspace, confirm ingestion, and query a window long enough to include monthly and exception-driven jobs. Microsoft’s AZMSApplicationMetricLogs table schema supports a query such as:
AZMSApplicationMetricLogs
| where Provider =~ "servicebus"
| where TimeGenerated >= ago(30d)
| summarize Records=count(),
MetricValue=sum(Value),
LastSeen=max(TimeGenerated)
by bin(TimeGenerated, 1h),
_SubscriptionId,
NamespaceName,
EntityName,
OperationName,
Protocol,
Outcome,
AuthType
| order by TimeGenerated desc
Pair this with application traces, deployment metadata, namespace metrics, firewall or proxy flow evidence, connection logs, and owner interviews. Azure’s monitoring documentation also notes that different log categories have different coverage; high-volume data operations are not automatically represented by every operational log.
Evidence state | Confidence | Required action |
SBMP observed | Confirmed blocker | Identify process from time, entity, operation, identity, network source, and deployment correlation |
AMQP observed; package known modern | Strong positive evidence | Complete semantic tests and full-window observation |
AMQP observed; package unknown or legacy | Transport clean, software risk open | Resolve binary/package and support status |
No records; diagnostics proven complete; workload exercised | Conditional evidence | Retain query, test record, and coverage proof |
No records; workload inactive or diagnostics uncertain | Unknown | Trigger controlled execution or preserve as a blocker |
Absence of rows is never automatically proof of absence. Record diagnostic enablement time, retention, namespace coverage, query window, expected workload schedule, and known blind spots beside every “zero SBMP” claim.
Map Each Namespace, Entity, and Workload to a Named Owner
A technically complete inventory still fails when it is ownerless. Assign a technical owner who can deploy and a business owner who can validate outcomes, down to each queue, topic, or subscription.
Create a workload matrix that can be reviewed daily:
Workload state | Meaning | Required disposition |
Named owner; active traffic; target approved | Normal migration work | Build, test, deploy by ring, and retain evidence. |
Unknown owner | No one can authorize or validate change | Escalate to subscription or resource-group leadership. |
Unknown protocol | Runtime transport is unproven | Enable diagnostics and exercise the workload. |
Unavailable source | Vendor or abandoned binary | Obtain evidence, replace, isolate, or retire. |
No recent traffic | Possibly dormant, not obsolete | Check schedules, runbooks, contracts, and last use. |
Shared entity; several applications | Blast radius or ordering may be coupled | Split evidence by identity and process; coordinate cutover. |
Exception requested | Deadline or semantic risk remains | Name approver, controls, expiry, and shutdown plan. |
The burn-down counts deployable workloads, grouped by criticality, protocol confidence, package, target build, tests, ring, owner, and exception expiry. Namespace-level AMQP evidence does not prove every caller is modern, and a clean repository does not exclude an external SBMP client.
Use API-first governance in transformation programs for explicit contracts and ownership, and production API management practices for gates and escalation, applied here to brokers rather than gateways.
The daily control is simple: every row must have named technical and business owners, a next action, and dated evidence. A team mailbox or “vendor” is not ownership. An unowned workload may be isolated only through a business-approved procedure that preserves messages and replay evidence.
Choose the Target SDK and Authentication Path by Runtime
Select the target by runtime, not by resemblance between class names. Microsoft’s supported sample index identifies Azure.Messaging.ServiceBus for .NET and com.azure:azure-messaging-servicebus for Java, alongside current libraries for Python, JavaScript/TypeScript, and Go. Azure Functions requires extension-level validation; managed connectors require product or vendor evidence rather than assumptions.
Runtime or integration | Named retirement? | Target | Validate |
.NET with a named legacy package | Yes | Azure.Messaging.ServiceBus | Client model, settlement, sessions, transactions, shutdown |
Java with the legacy Microsoft artifact | Yes | com.azure:azure-messaging-servicebus | Reactive/synchronous model, dependencies, processors, shutdown |
Azure Functions / WebJobs | Extension-dependent | Supported modern extension | Bindings, host settings, bundle, worker model |
Spring or Java Message Service adapter | Dependency-dependent | Supported adapter or SDK | Transitive artifact, JMS features, processor semantics |
JavaScript/TypeScript, Python, Go | No | Supported current SDK | Protocol, version, owner, identity, network |
Logic Apps / Power Automate | Managed connector | Verified supported connection | Vendor status, connection owner, execution evidence |
Vendor integration product | Unknown until proven | Supported release or replacement | Attestation, binary version, protocol evidence |
For Azure Functions, inventory the Service Bus extension or extension bundle, binding types, host.json behavior, worker model, and deployed package, not only application code. Microsoft’s extension 4.x-to-5.x migration guide states that version 5 uses the modern Service Bus SDK and includes breaking binding changes; version 4 support ended on March 31, 2025. The in-process worker model has a separate November 10, 2026 end-of-support date. Treat an app still using version 4 as an unsupported adjacent dependency, and do not confuse the worker-model date with the SDK and SBMP cutoff.
Move .NET Workloads to Azure.Messaging.ServiceBus
The official Azure SDK for .NET migration guide centers the design on a long-lived ServiceBusClient that creates senders, receivers, processors, and session processors, with ServiceBusAdministrationClient handling entity administration. Clients created from one ServiceBusClient share an AMQP connection, so creating and disposing a top-level client per message damages throughput and can exhaust connections.
Use an explicit mapping and test each row:
Legacy .NET intent | Modern client | Parity evidence |
QueueClient / TopicClient send | ServiceBusSender | Payload, properties, scheduled send, batch boundaries |
SubscriptionClient or handler registration | ServiceBusProcessor | Auto-complete, concurrency, prefetch, errors, drainage |
MessageReceiver | ServiceBusReceiver | Receive mode, settlement, deferral, dead-letter access |
Session client | ServiceBusSessionProcessor or session receiver | Session acceptance, state, ordering, lock renewal |
ManagementClient | ServiceBusAdministrationClient | Create/update/read/delete behavior and permissions |
Legacy Message | ServiceBusMessage / ServiceBusReceivedMessage | Field-by-field contract comparison |
An Azure.Messaging.ServiceBus migration should declare processor options rather than inherit them accidentally. Register message and error callbacks, start explicitly, stop intake before shutdown, drain in-flight handlers within a bound, and use IAsyncDisposable/await using for client lifetimes. The guide documents default auto-completion and that StopProcessingAsync stops new receives while active handlers can finish; set and test the intended behavior explicitly.
Move Java Workloads to com.azure:azure-messaging-servicebus
The official Azure SDK for Java migration guide moves from the old com.microsoft.azure:azure-servicebus artifact and package namespace to the version-7-generation com.azure:azure-messaging-servicebus library. It provides synchronous and asynchronous builders; the asynchronous model uses Project Reactor rather than the old CompletableFuture pattern. Do not transplant .NET assumptions into this design.
Map intent to Java-specific clients:
Legacy Java concern | Modern Java path | Validation focus |
Sending | ServiceBusSenderClient or async client | Batch tryAdd, scheduled messages, close behavior |
Pull receiving | ServiceBusReceiverClient or async client | Receive mode, settlement, backpressure, cancellation |
Callback processing | ServiceBusProcessorClient | Auto-complete choice, concurrency, prefetch, lock renewal, errors |
Sessions | Session processor or session receiver client | Session selection, state, concurrency, lock behavior |
Administration | Administration client in the Service Bus administration package | Permissions and entity/rule parity |
Transactions | Transaction context and cross-entity configuration | Supported broker operations, timeout, rollback evidence |
Build related clients from a common builder where supported, converge Azure dependencies, and inspect adapters for the old artifact. For prebuilt SAS tokens, use the guide’s SharedAccessSignature key, not the legacy token-key name, and do not combine it with key-name/key credentials. Configure processor behavior explicitly, then call stop() and close() during shutdown. The processor API documents automatic settlement unless disabled, with configurable concurrency, prefetch, and lock renewal.
Freeze Message Contracts and Delivery Semantics Before Refactoring
A migration test cannot detect semantic drift unless the old behavior has first been recorded. Freeze representative messages at the broker boundary and at the business-handler boundary. Store body bytes, not just deserialized objects, together with every property used for routing, correlation, deduplication, ordering, expiration, reply handling, diagnostics, or recovery.
Contract element | Capture | Migration risk |
Body and serialization | Bytes, schema/version, encoding | Changed decimals, dates, enums, or casing |
ContentType | Media type and charset | Wrong decoder selected |
Application properties | Names, values, data types | Coercion or filters change |
MessageId and CorrelationId | Generation and stability | Deduplication or tracing breaks |
Subject / legacy label | Exact value and mapping | Topic filters stop matching |
TTL and scheduled enqueue | Values and clock assumptions | Early expiry or changed availability |
Partition/session key | PartitionKey, SessionId, order boundary | Reordering or split sessions |
Reply fields | ReplyTo, ReplyToSessionId | Request/reply stalls |
Dead-letter metadata | Reason, description, delivery context | Recovery evidence is lost |
Tracing metadata | Trace IDs and custom properties | Diagnostics fragment |
Microsoft’s message payload and property model documents the broker properties and AMQP mappings, including the subject field used by modern clients where older code commonly used a label concept. Application-property types also need explicit testing rather than a string-only comparison.
For every consumer, add a semantic card: business side effects; idempotency key; duplicate-detection window, if configured; ordering scope; successful checkpoint; settlement point; replay safety; poison-message policy; dead-letter queue (DLQ) procedure; and manual recovery owner. This complements AsyncAPI and event-driven API documentation, but the migration baseline must include runtime behavior that an interface description alone cannot guarantee.
Keep schema redesign, serializer changes, property renaming, partitioning changes, and business retry-policy changes out of the same release unless they have independent tests and rollback. Acceptance requires golden input messages, captured outputs, filter results, DLQ records, and business reconciliation to match the approved baseline.
Translate the Legacy Client Model Without Changing Business Behavior
The modern SDKs provide better-aligned Azure client patterns, but there is no safe one-to-one rename. Reconstruct the lifecycle around shared clients, explicit senders and receivers, processors with declared options, and separate administration. Then prove behavior through the same contract fixtures and failure injections used against the old implementation.
Rebuild Senders, Receivers, Processors, Sessions, and Administration
Use this implementation map as a code-review checklist:
Concern | Implementation decision | Validation |
Client lifetime | Long-lived top-level client per namespace and credential boundary | Connections and reconnect under load |
Sending | Reuse sender; await sends; use safe batches | No fire-and-forget loss; deterministic oversize handling |
Pull receiving | Receive mode, wait, batch size, settlement | Partial failures and cancellation |
Processor | Auto-complete, concurrency, prefetch, retry, error callback | Handler, broker, network, and credential failures |
Sessions | Concurrency, acceptance, state, idle timeout | Per-session order and lock loss |
Administration | Separate client and least-privilege role | Audited entity and rule changes |
Transactions | Scope, send-via configuration, operation order | Commit, rollback, timeout |
Shutdown | Stop intake, cancel, drain, close | No abandoned or unbounded work |
For batching, use the SDK batch and add until TryAdd/tryAdd rejects the next message; a plain list checked before serialization is unsafe. Batch settlement is not universally atomic, so represent partial outcomes and retry item by item. Where code uses AMQP annotations or nonstandard sections, compare the modern SDK’s full AMQP message access with captured legacy messages.
Sessions create an exclusive lock and ordering boundary. Test selection, state, concurrency, renewal, abandonment, and restart. Microsoft’s Service Bus session documentation cautions that DLQ replay gets new enqueue and sequence positions, so it cannot restore original global order.
Broker transactions cover only supported Service Bus operations; external databases and providers are not enlisted. Microsoft documents cross-entity patterns, a two-minute timeout, and no automatic retry for a failed transaction scope in its Service Bus transaction documentation.
Preserve Settlement, Lock Renewal, Retry, and Dead-Letter Behavior
Peek-lock receiving gives the handler time-limited exclusive access, followed by one of several outcomes. Microsoft’s guide to transfers, locks, and settlement explains why a settlement call can fail even after business work has succeeded. That uncertainty is the root of many duplicate side effects.
Event | Broker result | Handler obligation |
Complete | Removed if acknowledgement succeeds | Persist success with an idempotency decision |
Abandon | Available for redelivery | Retain failure context; avoid repeated side effects |
Defer | Retained for sequence-number retrieval | Persist sequence number and owner |
Dead-letter | Moved to DLQ | Preserve reason, identifiers, and replay decision |
Lock expires | May be redelivered | Reconcile the prior side effect |
Process crashes | Settlement may not occur | Recover from durable business state |
Network drops after settlement request | Acknowledgement may be unknown | Expect redelivery; suppress duplicate effects |
Receive-and-delete | Removed on transfer | Use only when loss is accepted |
Configure lock renewal for the measured handler duration, not as a substitute for bounded work. Prefetch starts the lock clock before processing; raising prefetch can increase throughput but can also cause locked messages to wait until they expire. Set processor auto-completion, maximum concurrency, prefetch, lock renewal, retry policy, session concurrency, error callback behavior, handler cancellation, and shutdown drainage explicitly in both languages. Microsoft’s performance guidance for Azure Service Bus recommends reusing clients and tuning batching, prefetch, and topology with measured workloads.
Unexplained lock-lost growth, a handler that performs a side effect before establishing an idempotency decision, or a shutdown that terminates in-flight work without recovery evidence must stop promotion. Pause intake, inspect business state and delivery count, settle only when the outcome is known, and replay under a recorded operator decision.
Separate SDK Migration From the Move to Microsoft Entra ID
Microsoft recommends passwordless authentication with Microsoft Entra ID and Azure role-based access control (RBAC) where possible, while managed identities remove stored application credentials. That does not make identity a harmless add-on to the SDK change. A new SDK, new token source, new role assignment, and new network dependency in one release create four simultaneous failure domains.
Choose one of three paths deliberately:
Path | Use when | Main benefit | Exit requirement |
Modern SDK with existing Shared Access Signature (SAS) connection string temporarily | Semantic risk is high and test capacity is limited | Isolates SDK behavior first | Dated plan to migrate and remove secrets |
Modern SDK with Entra service principal | Workload runs where managed identity is unavailable | Central RBAC and credential governance | Rotation, secret/certificate controls, denied-access tests |
Modern SDK with managed identity | Supported Azure host and identity lifecycle are proven | No application secret stored | Role scope, token path, failover, and emergency access verified |
Use the narrowest applicable built-in role: Azure Service Bus Data Sender, Data Receiver, or Data Owner, scoped to the entity or namespace where practical. Test allowed and forbidden operations, token acquisition after restart, local credentials, every deployment slot or scale unit, and credential expiry. Microsoft’s passwordless connection migration guide and managed-identity guidance for Service Bus document the supported model.
Official guidance gives different propagation windows: the passwordless guide says assignments usually take one or two minutes and rarely up to eight; managed-identity guidance says up to five. Treat propagation as asynchronous and use bounded validation retries. When validating role removal, account for cached managed-identity tokens that may remain valid for up to 24 hours unless the application restarts.
Retain SAS only while a tested rollback needs it. After soak, prove removal from configuration, secret stores, deployment variables, local files, and break-glass procedures; disable local authentication only after every legitimate caller passes an Entra test.
Prove AMQP Connectivity Through Firewalls, Proxies, and Private Endpoints
Azure Service Bus uses AMQP as its primary wire protocol. Microsoft documents AMQP over TCP on ports 5671 and 5672 and AMQP over WebSockets on port 443; HTTPS on port 443 can also be needed for token acquisition and some management operations. WebSockets can traverse restrictive networks but add connection overhead, so transport choice should be measured rather than treated as cosmetic. Microsoft’s Service Bus transport and firewall guidance provides the supported port model.
Test from every real host class, including production subnets, scale sets, Kubernetes node pools, Functions plans, on-premises hosts, desktop networks, and recovery regions, rather than only from a developer laptop.
Test | Evidence | Blocking failure |
DNS | Resolved namespace and private-link names | Resolution differs from design |
TCP/TLS | Negotiated connection on required port | Firewall, proxy, rule, or inspection failure |
WebSockets fallback | Explicit proxy-path test | Upgrade blocked or excessive churn |
Token path | Entra token from workload identity | HTTPS, proxy, identity endpoint, or DNS failure |
Private endpoint | Route and private DNS proof | Traffic escapes publicly or resolves incorrectly |
Connection reuse | Stable connections under load | Per-message connections or port exhaustion |
Regional behavior | Latency and reconnect from both sites | Lock budget or throughput fails |
Failure injection | Controlled deny, DNS failure, proxy reset | Silent retry loop or unalerted backlog |
Do not hard-code namespace IP addresses discovered from DNS. Validate documented outbound paths, private endpoints, and TLS inspection explicitly.
Promote only after sustained send, receive, token-renewal, reconnect, and management tests pass from production hosts using the expected transport. A laptop-only pass, an unmeasured WebSockets fallback, or inconsistent private DNS across scale units blocks release. Recovery pauses intake before lock storms, restores the supported transport configuration, drains safely, and replays only after the path is clean.
Build Compatibility Tests for Ordering, Idempotency, and Transactions
The harness must run known fixtures through both implementations and compare broker-visible messages with business results. Version its tolerances so thresholds remain approved requirements.
Test family | Vary or inject | Required evidence |
Contract | Body, properties, subject, TTL, scheduling, replies | Byte/property diff and filter result |
Delivery | Duplicate send, redelivery, lock expiry, abandon | Stable IDs and one business outcome |
Ordering | Partitions, sessions, concurrent handlers | Sequence within the declared boundary |
Settlement | Complete, defer, dead-letter, uncertain acknowledgement | Delivery count, DLQ metadata, operator path |
Processor | Concurrency, prefetch, auto-complete, cancellation | No silent loss; bounded drainage |
Resilience | Restart, network, credential, dependency failure | Retry trace, backlog recovery, no poison loop |
Transactions | Commit, rollback, cross-entity operation, timeout | Broker state and compensation |
Performance | Peak rate, batches, large messages, latency | Throughput, latency, connections, throttling |
Recovery | Replay, session state, scheduled/deferred messages | Reconciliation and replay evidence |
The reason to emphasize backend idempotency and distributed-system skills is visible in an order-payment failure window. Assume the message has stable MessageId=pay:order-74219:v1 and the handler uses peek-lock:
1. The handler receives the message and begins a database transaction.
2. It inserts an idempotency record keyed by MessageId and effect type, posts the payment state, and marks the effect COMMITTED.
3. The database transaction commits.
4. The handler calls complete, but the network drops before the settlement acknowledgement reaches the client.
5. The lock expires and Service Bus redelivers the message.
6. The next handler finds the committed idempotency record, does not repeat the financial action, records servicebus_duplicate_delivery_suppressed_total, and completes the message.
7. An operator can prove the outcome from the idempotency row, message ID, delivery count, trace ID, settlement error, reconciliation result, and final settlement.
Configured duplicate detection can reject repeated stable MessageId values within its history window, but it does not remove the consumer failure window; Microsoft also documents a throughput tradeoff as the window grows in its duplicate-detection documentation.
Do not claim exactly-once processing: external databases and payment providers are outside the broker transaction. When idempotency state is ambiguous after redelivery, stop the consumer or session, reconcile the effect, then complete, replay, or dead-letter under an accountable decision.
Rehearse Parallel Operation Without Creating False Shadow Consumers
A second receiver attached to the same queue is a competing consumer: it removes messages from the pool that the original consumer would otherwise receive. It is not a passive mirror. By contrast, each topic subscription receives its own copy, subject to its filters, which makes a temporary cloned subscription a possible comparison path when filters, forwarding, sessions, retention, and cleanup are validated. Microsoft’s Azure Service Bus messaging overview describes this queue-versus-subscription model.
Workload | Safe rehearsal | Primary control |
Topic consumer | Temporary cloned subscription with equivalent filters | Compare outcomes; suppress side effects |
Queue consumer | Test namespace with approved captures | Sanitize data; preserve contract and order cases |
Queue with replay | Controlled copy to an isolated entity | Stable IDs, replay ledger, bounded window |
Producer | Durable outbox feeding both targets | Reconcile asymmetric publication |
Managed connector | Vendor-supported test connection | Prove version and transport |
Session workload | Isolated sessions or valid cloned subscription | Preserve session IDs and order |
Application-level duplication can be safe only when the duplication itself is durable. A dual write performed as two independent sends can succeed on one path and fail on the other, creating a reconciliation problem more dangerous than the original migration. Where dual publication is unavoidable, write one durable outbox or intent record, use stable identifiers on both messages, track per-target delivery, compare results, and define an explicit stop date.
For shadow processing, suppress irreversible actions and compare computed decisions, not just received counts. Validate filter matches, headers, session routing, dead-letter outcomes, latency, and ordering. A “shadow” that calls a live payment, email, fulfillment, or entitlement service is a second production executor.
Any comparison path that steals queue messages, creates irreversible duplicate actions, or cannot reconcile asymmetric sends must be disabled. Preserve the intent or replay ledger, drain only the isolated entity, and reconcile every unmatched identifier before resuming.
Roll Out by Producer, Consumer, and Namespace Risk Rings
A namespace-wide “big bang” removes fault isolation. Ring by role and semantic risk, and promote only when telemetry and business reconciliation agree. These soak periods are practitioner recommendations; extend them to cover real peaks and schedules.
Ring | Entry | Recommended soak | Promotion evidence | Rollback trigger |
Lab / controlled replay | Contract and target build complete | Full suite plus restart and failure cycle | No unaccounted message or business difference | Any contract or recovery mismatch |
Noncritical producer | Consumer compatibility proven | Four hours and one peak | Send, batch, and downstream parity | Missing, malformed, or asymmetric message |
Noncritical consumer / low-volume subscription | Idempotency and DLQ path proven | 24 hours or one business cycle | Settlement, backlog, and outputs match | Duplicate effect, lock loss, poison loop |
Session workload | Session and state recovery tests pass | One session cycle plus restart | Per-session order and state match | Ordering or session-lock anomaly |
Transactional workload | Broker transaction and compensation tests pass | One full business cycle with failure injection | Commit/rollback evidence reconciles | Uncertain or split outcome |
High-throughput / critical namespace | Capacity test and rollback approved | Two peak periods, normally 48 hours | Stable throughput, latency, throttling, backlog, and KPIs | Sustained degradation or drift |
Managed integration | Vendor evidence and isolated test complete | One real scheduled execution | Version, protocol, owner, and output proven | Missing proof or unexpected transport |
Each ring needs a release owner, business validator, timestamps, build/configuration hashes, dashboard, rollback decision-maker, and sign-off. Producers and consumers may move separately only when every coexisting old/new pairing is proven.
Rollback means restoring the last supported AMQP-capable build or pausing intake for drain and replay. At or after September 30, 2026, rollback never means SBMP. Stop rather than roll back blindly when the prior build is unsupported, side effects are ambiguous, schemas changed, or messages were partly processed.
Promote only after representative traffic, a restart, and a controlled dependency or network failure. Calendar pressure is not evidence, and no exception can authorize SBMP beyond the deadline.
Observe Semantic Drift, Backlogs, Failures, and Duplicate Side Effects
Infrastructure dashboards can remain green while business behavior diverges. Build one migration view that combines Service Bus metrics, protocol evidence, application traces, deployment data, and business reconciliation. The observability patterns in OpenTelemetry for backend observability are useful for trace correlation, but the migration also needs broker and domain-specific controls.
Signal group | Monitor | Interpretation |
Connections and protocol | Connections, reconnects, AMQP/SBMP mix, transport | Old callers or connection churn |
Service requests | Success/failure, server/user errors, throttling | Authorization, client, service, or capacity fault |
Queue health | Active/DLQ count, oldest age, message rate | Backlog growth or poison loop |
Processor behavior | Exceptions, lock loss, retries, duration, cancellation | Settlement or shutdown drift |
Performance | Throughput, latency, batch fill, prefetch | Approved capacity envelope |
Business integrity | Duplicate actions, missing records, order violations, reconciliation | Workflow meaning remains intact |
Deployment context | Build, configuration, identity, host, ring, time | Attribute changes accurately |
Propagate identifiers and trace context without sensitive payloads. Record when the business result becomes durable and when settlement is attempted. Alert separately on duplicate delivery and duplicate side effect; only the latter necessarily indicates a business defect.
A zero-SBMP chart must show its window, namespace coverage, diagnostic health, and expected executions. A flat DLQ is not healthy if consumers stopped and active backlog rises. Each dashboard tile needs an owner, query, stop threshold, and recovery action.
Block release for unexplained reconciliation differences, rising oldest-message age, ordering violations, sustained lock loss, or critical telemetry gaps. Recovery requires baseline backlog, reconciled ambiguous identifiers, accounted replays, and a clean protocol view.
Remove Legacy Packages, SBMP Rules, Connection Strings, and Exceptions
Decommissioning is a separate release phase. A modern deployment does not remove an old package from a shared library, delete a forgotten connection string from a secret store, or close a vendor exception automatically. Build a proof package that an auditor or incident commander can reproduce without relying on a project spreadsheet’s green cell.
Evidence domain | Required proof |
Source and dependencies | No direct or transitive legacy references; lock and central version files are clean. |
Built artifacts | Assembly/JAR, shaded package, image-layer, and software-bill-of-materials scans are clean. |
Runtime | Full-window telemetry shows no SBMP; every expected periodic workload ran. |
Network | Obsolete SBMP exceptions are removed; required AMQP/HTTPS paths are documented. |
Configuration | Old transport flags, package settings, and unused connection-string keys are removed. |
Authentication | Retired SAS policies, keys, connection strings, and secrets are removed after rollback closes. |
Operations | Dashboards, alerts, runbooks, templates, and support procedures reference modern clients. |
External dependencies | Vendor cases close with version and protocol proof; managed connectors are validated. |
Governance | Exceptions expire or become approved residual risks with owner and containment. |
Scan dependencies in continuous integration and the final artifact. Recheck deployed environments after rollback closes, including dormant machines, slots, desktops, and recovery images. Preserve credentials only until the supported rollback expires, then prove the retired credential fails.
Delete obsolete SBMP network allowances only after checking shared uses. Retire dashboards only after replacements work, and mark old runbooks so responders cannot restore an SBMP build.
Decommissioning closes only when two reviewers can trace every row to clean source and artifact evidence, modern transport, a supported build, a named owner, and closed credentials or exceptions. Unavailable binaries, unexecuted jobs, and unexplained connections remain open risks.
Build a Deadline-Relative Cutover and Post-Deadline Remediation Plan
Define T-0 as September 30, 2026, the official legacy-SDK retirement and SBMP cutoff. The plan below remains usable before the date, on it, and after it. Freeze unrelated messaging changes, use one migration command cadence, and maintain a single decision log. An organization starting after T-0 should treat every residual SBMP dependency as an incident and complete the omitted evidence gates rather than skipping directly to package replacement.
Window | Required work | Exit gate |
T-30 to T-22 | Inventory code, binaries, traffic, owners, criticality, sessions, transactions, and hidden integrations. | Every workload has an owner, protocol confidence, impact, and target. |
T-21 to T-15 | Build .NET/Java targets; freeze contracts; test behavior, identity, network, failure, and rollback. | Golden-message and recovery tests pass. |
T-14 to T-8 | Move low-risk producers, consumers, and subscriptions; validate Functions, adapters, connectors, and vendors. | Ring sign-offs and reconciliation are clean. |
T-7 to T-3 | Cut session, transactional, critical, and high-throughput workloads; exercise rare jobs. | Peak evidence, business approval, and supported rollback are recorded. |
T-2 to T-1 | Freeze unrelated releases; finish cutovers; rerun scans and protocol queries; remove obsolete access where safe. | No unknown owner, protocol, source, schedule, or vendor status. |
T-0: September 30, 2026 | Run final protocol checks, attestations, exception review, key decisions, and incident handoff. | Zero SBMP dependence and no unnamed legacy workload. |
T+1 to T+7 | Isolate residual workloads; migrate or replace them; reconcile ambiguous actions; replay safely. | Supported AMQP paths with no unexplained backlog or outcome. |
T+8 to T+30 | Remove obsolete secrets, rules, dashboards, and runbooks; close vendors; repeat zero-SBMP verification. | Complete decommission evidence and approved residual risks. |
For every migration or remediation decision, record the workload and entity, build and package versions, identity and network path, fixture and test results, observation window, protocol query, technical metrics, business reconciliation, approvals, rollback trigger, and final disposition.
Before T-0, use at least a daily decision cadence and increase it during the highest-risk cutover window. At and after T-0, any residual SBMP dependency should move under incident command. Engineering owns behavior; platform owns diagnostics and network; security owns identity and credentials; application owners own recovery; business validators own reconciliation; and the program lead owns cross-team escalation.
Pause promotion or operation for unexplained SBMP, unresolved source or vendor status, an unexecuted critical workload, a duplicate business effect, an ordering failure, unexpected DLQ or backlog growth, or an unsafe rollback. Recover through a supported AMQP build or a documented pause, drain, reconciliation, and replay path. SBMP is not an acceptable rollback at or after T-0.
The T-0 acceptance condition is not “migration work started” or “AMQP observed.” It is zero SBMP dependence, no unnamed legacy workload, supported builds for every active path, completed semantic and failure tests, verified identity and network routes, contained residual risks, and reproducible evidence. For a post-deadline remediation, closure requires the same proof plus reconciliation of every failed, delayed, or ambiguous business action caused by the residual dependency.
A successful AMQP connection proves only that one process reached one endpoint. Completion requires message bodies and properties to retain their meaning; ordering, sessions, and transactions to behave as designed; settlement and retry windows to be understood; duplicate side effects to be suppressed; network and token paths to survive failure; dashboards to expose backlog and semantic drift; and evidence to show that unsupported packages, SBMP, credentials, rules, and exceptions are gone.
Whether assessed before or after September 30, 2026, the question is the same: can the team handle replay, lock loss, restart, proxy failure, credential change, and ambiguous settlement without guessing? Fixtures, traces, reconciliations, named owners, and signed gates make the answer defensible.
The Refonte Learning APIs Developer Program is described as a three-month program requiring about 10–12 hours per week. Its verified coverage includes authentication and authorization, API testing, error handling and logging, versioning and deprecation, microservices, performance optimization, API security, hands-on projects, and mentor access. These foundations support disciplined integration work; the page does not list Azure Service Bus, AMQP, SBMP, or the named SDK migration, so product-specific coverage should be confirmed separately.Microsoft established September 30, 2026 as the retirement date for the named legacy Azure Service Bus SDK libraries and as the cutoff for Service Bus Messaging Protocol (SBMP) workloads. Organizations that have not completed the migration need evidence that every active sender and consumer uses a supported client and transport. After the cutoff, any remaining SBMP dependency becomes a production-remediation issue rather than an ordinary upgrade task.
The retirement creates two different risks. The WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus, and legacy Java com.microsoft.azure.servicebus libraries lose official support and updates, although an old binary might still start. SBMP is different: Microsoft states that workloads cannot use the protocol after September 30, 2026. A technically executable binary is therefore not evidence of a viable transport. Microsoft’s Azure Service Bus retirement documentation makes that distinction explicit.
This runbook works backward from production proof. It builds a verified estate, assigns every namespace and entity to an owner, freezes message contracts and delivery semantics, maps .NET and Java behavior to supported clients, isolates identity and network changes, tests failure windows, rehearses coexistence safely, deploys by risk ring, and ends with an auditable zero-legacy evidence package. The test is not merely whether the new client connects; it is whether every end-to-end workflow still produces the same business result under retries, lock loss, restarts, poison messages, and uncertain settlement acknowledgements.
Define the Exact Retirement Scope and the Failure Modes It Creates
The first control is a scope statement that procurement, engineering, security, and site reliability engineers (SREs) interpret the same way. The retirement notice does not retire the Azure Service Bus service. Microsoft established September 30, 2026 as the point at which the named legacy software development kits (SDKs) leave official support and SBMP becomes unavailable. Current JavaScript/TypeScript, Python, and Go Azure SDKs are not named in the notice, although their applications still belong in the inventory.
Item | Status from September 30, 2026 | Required action |
WindowsAzure.ServiceBus | Retired and unsupported | Replace it; isolate and migrate any post-cutoff discovery. |
Microsoft.Azure.ServiceBus | Retired and unsupported | Move to Azure.Messaging.ServiceBus and prove semantic parity. |
Legacy Java com.microsoft.azure.servicebus / com.microsoft.azure:azure-servicebus | Retired and unsupported | Move to com.azure:azure-messaging-servicebus and test Java behavior. |
SBMP transport | Unavailable after the cutoff | Eliminate by the cutoff; isolate any later dependency. |
JavaScript, Python, and Go SDKs not named in the notice | Outside this library retirement | Validate version, transport, ownership, identity, network, and wrappers. |
An overlooked SBMP process cannot send or receive after the cutoff. A legacy library using AMQP may continue to execute but is unsupported. A modern client can connect while changed auto-completion, concurrency, batching, retries, lock renewal, session handling, or shutdown creates duplicates, reordering, dead-letter queue growth, or a silent backlog.
Treat unexplained SBMP telemetry, an unknown binary owner, unavailable source, or an unexecuted workload as open risk. The discipline described in Refonte Learning’s guide to controlled API deprecation and versioning applies, but no rollback at or after September 30, 2026 may reinstate SBMP.
Promotion requires every workload to have a target, semantic baseline, test result, and supported AMQP-capable rollback. Unexplained SBMP or an irreconcilable business result blocks promotion. Recovery returns to a supported AMQP build or pauses intake while operators drain, reconcile, and replay.
Inventory Every Legacy Package, Protocol, Framework, and Hidden Consumer
Repository search is only one evidence stream. Service Bus clients can hide in shared libraries, Azure Functions extensions, WebJobs bindings, Logic Apps, Power Automate flows, integration platforms, scheduled tasks, desktop software, vendor binaries, framework starters, or images built months ago. A survey of serverless APIs and Azure Functions triggers explains the architectural setting; this retirement requires a deeper deployment-by-deployment inventory.
Use one authoritative record per deployable process or managed integration. At minimum, capture the following schema:
Field group | Required fields |
Software identity | Repository or binary, language, runtime, package and exact version, direct or transitive dependency, process/framework/connector, artifact hash |
Hosting and Azure scope | Host platform, Azure subscription, resource group, namespace, queue/topic/subscription, region |
Messaging behavior | Producer/consumer role, session or transaction use, protocol/transport configuration, authentication method, network path |
Ownership and risk | Technical owner, business owner, business criticality, message volume, peak rate, deployment frequency |
Evidence and plan | Last observed traffic, source availability, migration status, test status, exception owner, exception expiry |
Do not combine several binaries under “order platform” when they deploy independently. A command-line reconciler, web application, and overnight scheduler can reference the same namespace but differ in package, identity, transport, and execution frequency.
Find Compile-Time Dependencies Across .NET and Java Estates
For .NET, scan solution and project files, packages.config, PackageReference entries, packages.lock.json, Directory.Packages.props, generated .deps.json files, publish directories, NuGet caches, software bills of materials, and container layers. Resolve transitive packages rather than searching only source text. A practical first pass is:
dotnet list Commerce.sln package --include-transitive
grep -RInE 'WindowsAzure\.ServiceBus|Microsoft\.Azure\.ServiceBus' .
For Java, inspect Maven pom.xml files, Gradle build files and version catalogs, dependency-lock files, Spring or integration starters, shaded or “fat” JAR contents, application-server libraries, artifact repositories, and container layers. Generate resolved trees, because a parent platform or adapter can pull the legacy artifact indirectly:
mvn dependency:tree -Dincludes=com.microsoft.azure:azure-servicebus
./gradlew dependencies
grep -RInE 'com\.microsoft\.azure\.servicebus|azure-servicebus' .
Also search configuration and infrastructure as code for namespace hostnames, connection-string keys, transport settings, Service Bus trigger declarations, deployment slots, and old secret names. Compare source findings with the actual artifact deployed in each environment; a clean main branch does not prove that a long-lived virtual machine or desktop installation is clean.
When source is unavailable, record the binary hash, vendor, version, deployment location, namespace access, observed traffic, and contract owner. Inspect package manifests and runtime dependencies where legally and technically permitted, then obtain dated vendor evidence for SDK and protocol. Until the binary is upgraded, isolated, replaced, or disabled, mark it unavailable source: open risk.
Use Runtime Telemetry to Prove Where SBMP Still Exists
Azure Monitor’s AZMSApplicationMetricLogs resource-specific table includes fields such as NamespaceName, EntityName, OperationName, Outcome, AuthType, and Protocol; documented protocol values include AMQP and SBMP. Enable the relevant diagnostics on every in-scope namespace, route them to a controlled Log Analytics workspace, confirm ingestion, and query a window long enough to include monthly and exception-driven jobs. Microsoft’s AZMSApplicationMetricLogs table schema supports a query such as:
AZMSApplicationMetricLogs
| where Provider =~ "servicebus"
| where TimeGenerated >= ago(30d)
| summarize Records=count(),
MetricValue=sum(Value),
LastSeen=max(TimeGenerated)
by bin(TimeGenerated, 1h),
_SubscriptionId,
NamespaceName,
EntityName,
OperationName,
Protocol,
Outcome,
AuthType
| order by TimeGenerated desc
Pair this with application traces, deployment metadata, namespace metrics, firewall or proxy flow evidence, connection logs, and owner interviews. Azure’s monitoring documentation also notes that different log categories have different coverage; high-volume data operations are not automatically represented by every operational log.
Evidence state | Confidence | Required action |
SBMP observed | Confirmed blocker | Identify process from time, entity, operation, identity, network source, and deployment correlation |
AMQP observed; package known modern | Strong positive evidence | Complete semantic tests and full-window observation |
AMQP observed; package unknown or legacy | Transport clean, software risk open | Resolve binary/package and support status |
No records; diagnostics proven complete; workload exercised | Conditional evidence | Retain query, test record, and coverage proof |
No records; workload inactive or diagnostics uncertain | Unknown | Trigger controlled execution or preserve as a blocker |
Absence of rows is never automatically proof of absence. Record diagnostic enablement time, retention, namespace coverage, query window, expected workload schedule, and known blind spots beside every “zero SBMP” claim.
Map Each Namespace, Entity, and Workload to a Named Owner
A technically complete inventory still fails when it is ownerless. Assign a technical owner who can deploy and a business owner who can validate outcomes, down to each queue, topic, or subscription.
Create a workload matrix that can be reviewed daily:
Workload state | Meaning | Required disposition |
Named owner; active traffic; target approved | Normal migration work | Build, test, deploy by ring, and retain evidence. |
Unknown owner | No one can authorize or validate change | Escalate to subscription or resource-group leadership. |
Unknown protocol | Runtime transport is unproven | Enable diagnostics and exercise the workload. |
Unavailable source | Vendor or abandoned binary | Obtain evidence, replace, isolate, or retire. |
No recent traffic | Possibly dormant, not obsolete | Check schedules, runbooks, contracts, and last use. |
Shared entity; several applications | Blast radius or ordering may be coupled | Split evidence by identity and process; coordinate cutover. |
Exception requested | Deadline or semantic risk remains | Name approver, controls, expiry, and shutdown plan. |
The burn-down counts deployable workloads, grouped by criticality, protocol confidence, package, target build, tests, ring, owner, and exception expiry. Namespace-level AMQP evidence does not prove every caller is modern, and a clean repository does not exclude an external SBMP client.
Use API-first governance in transformation programs for explicit contracts and ownership, and production API management practices for gates and escalation, applied here to brokers rather than gateways.
The daily control is simple: every row must have named technical and business owners, a next action, and dated evidence. A team mailbox or “vendor” is not ownership. An unowned workload may be isolated only through a business-approved procedure that preserves messages and replay evidence.
Choose the Target SDK and Authentication Path by Runtime
Select the target by runtime, not by resemblance between class names. Microsoft’s supported sample index identifies Azure.Messaging.ServiceBus for .NET and com.azure:azure-messaging-servicebus for Java, alongside current libraries for Python, JavaScript/TypeScript, and Go. Azure Functions requires extension-level validation; managed connectors require product or vendor evidence rather than assumptions.
Runtime or integration | Named retirement? | Target | Validate |
.NET with a named legacy package | Yes | Azure.Messaging.ServiceBus | Client model, settlement, sessions, transactions, shutdown |
Java with the legacy Microsoft artifact | Yes | com.azure:azure-messaging-servicebus | Reactive/synchronous model, dependencies, processors, shutdown |
Azure Functions / WebJobs | Extension-dependent | Supported modern extension | Bindings, host settings, bundle, worker model |
Spring or Java Message Service adapter | Dependency-dependent | Supported adapter or SDK | Transitive artifact, JMS features, processor semantics |
JavaScript/TypeScript, Python, Go | No | Supported current SDK | Protocol, version, owner, identity, network |
Logic Apps / Power Automate | Managed connector | Verified supported connection | Vendor status, connection owner, execution evidence |
Vendor integration product | Unknown until proven | Supported release or replacement | Attestation, binary version, protocol evidence |
For Azure Functions, inventory the Service Bus extension or extension bundle, binding types, host.json behavior, worker model, and deployed package, not only application code. Microsoft’s extension 4.x-to-5.x migration guide states that version 5 uses the modern Service Bus SDK and includes breaking binding changes; version 4 support ended on March 31, 2025. The in-process worker model has a separate November 10, 2026 end-of-support date. Treat an app still using version 4 as an unsupported adjacent dependency, and do not confuse the worker-model date with the SDK and SBMP cutoff.
Move .NET Workloads to Azure.Messaging.ServiceBus
The official Azure SDK for .NET migration guide centers the design on a long-lived ServiceBusClient that creates senders, receivers, processors, and session processors, with ServiceBusAdministrationClient handling entity administration. Clients created from one ServiceBusClient share an AMQP connection, so creating and disposing a top-level client per message damages throughput and can exhaust connections.
Use an explicit mapping and test each row:
Legacy .NET intent | Modern client | Parity evidence |
QueueClient / TopicClient send | ServiceBusSender | Payload, properties, scheduled send, batch boundaries |
SubscriptionClient or handler registration | ServiceBusProcessor | Auto-complete, concurrency, prefetch, errors, drainage |
MessageReceiver | ServiceBusReceiver | Receive mode, settlement, deferral, dead-letter access |
Session client | ServiceBusSessionProcessor or session receiver | Session acceptance, state, ordering, lock renewal |
ManagementClient | ServiceBusAdministrationClient | Create/update/read/delete behavior and permissions |
Legacy Message | ServiceBusMessage / ServiceBusReceivedMessage | Field-by-field contract comparison |
An Azure.Messaging.ServiceBus migration should declare processor options rather than inherit them accidentally. Register message and error callbacks, start explicitly, stop intake before shutdown, drain in-flight handlers within a bound, and use IAsyncDisposable/await using for client lifetimes. The guide documents default auto-completion and that StopProcessingAsync stops new receives while active handlers can finish; set and test the intended behavior explicitly.
Move Java Workloads to com.azure:azure-messaging-servicebus
The official Azure SDK for Java migration guide moves from the old com.microsoft.azure:azure-servicebus artifact and package namespace to the version-7-generation com.azure:azure-messaging-servicebus library. It provides synchronous and asynchronous builders; the asynchronous model uses Project Reactor rather than the old CompletableFuture pattern. Do not transplant .NET assumptions into this design.
Map intent to Java-specific clients:
Legacy Java concern | Modern Java path | Validation focus |
Sending | ServiceBusSenderClient or async client | Batch tryAdd, scheduled messages, close behavior |
Pull receiving | ServiceBusReceiverClient or async client | Receive mode, settlement, backpressure, cancellation |
Callback processing | ServiceBusProcessorClient | Auto-complete choice, concurrency, prefetch, lock renewal, errors |
Sessions | Session processor or session receiver client | Session selection, state, concurrency, lock behavior |
Administration | Administration client in the Service Bus administration package | Permissions and entity/rule parity |
Transactions | Transaction context and cross-entity configuration | Supported broker operations, timeout, rollback evidence |
Build related clients from a common builder where supported, converge Azure dependencies, and inspect adapters for the old artifact. For prebuilt SAS tokens, use the guide’s SharedAccessSignature key, not the legacy token-key name, and do not combine it with key-name/key credentials. Configure processor behavior explicitly, then call stop() and close() during shutdown. The processor API documents automatic settlement unless disabled, with configurable concurrency, prefetch, and lock renewal.
Freeze Message Contracts and Delivery Semantics Before Refactoring
A migration test cannot detect semantic drift unless the old behavior has first been recorded. Freeze representative messages at the broker boundary and at the business-handler boundary. Store body bytes, not just deserialized objects, together with every property used for routing, correlation, deduplication, ordering, expiration, reply handling, diagnostics, or recovery.
Contract element | Capture | Migration risk |
Body and serialization | Bytes, schema/version, encoding | Changed decimals, dates, enums, or casing |
ContentType | Media type and charset | Wrong decoder selected |
Application properties | Names, values, data types | Coercion or filters change |
MessageId and CorrelationId | Generation and stability | Deduplication or tracing breaks |
Subject / legacy label | Exact value and mapping | Topic filters stop matching |
TTL and scheduled enqueue | Values and clock assumptions | Early expiry or changed availability |
Partition/session key | PartitionKey, SessionId, order boundary | Reordering or split sessions |
Reply fields | ReplyTo, ReplyToSessionId | Request/reply stalls |
Dead-letter metadata | Reason, description, delivery context | Recovery evidence is lost |
Tracing metadata | Trace IDs and custom properties | Diagnostics fragment |
Microsoft’s message payload and property model documents the broker properties and AMQP mappings, including the subject field used by modern clients where older code commonly used a label concept. Application-property types also need explicit testing rather than a string-only comparison.
For every consumer, add a semantic card: business side effects; idempotency key; duplicate-detection window, if configured; ordering scope; successful checkpoint; settlement point; replay safety; poison-message policy; dead-letter queue (DLQ) procedure; and manual recovery owner. This complements AsyncAPI and event-driven API documentation, but the migration baseline must include runtime behavior that an interface description alone cannot guarantee.
Keep schema redesign, serializer changes, property renaming, partitioning changes, and business retry-policy changes out of the same release unless they have independent tests and rollback. Acceptance requires golden input messages, captured outputs, filter results, DLQ records, and business reconciliation to match the approved baseline.
Translate the Legacy Client Model Without Changing Business Behavior
The modern SDKs provide better-aligned Azure client patterns, but there is no safe one-to-one rename. Reconstruct the lifecycle around shared clients, explicit senders and receivers, processors with declared options, and separate administration. Then prove behavior through the same contract fixtures and failure injections used against the old implementation.
Rebuild Senders, Receivers, Processors, Sessions, and Administration
Use this implementation map as a code-review checklist:
Concern | Implementation decision | Validation |
Client lifetime | Long-lived top-level client per namespace and credential boundary | Connections and reconnect under load |
Sending | Reuse sender; await sends; use safe batches | No fire-and-forget loss; deterministic oversize handling |
Pull receiving | Receive mode, wait, batch size, settlement | Partial failures and cancellation |
Processor | Auto-complete, concurrency, prefetch, retry, error callback | Handler, broker, network, and credential failures |
Sessions | Concurrency, acceptance, state, idle timeout | Per-session order and lock loss |
Administration | Separate client and least-privilege role | Audited entity and rule changes |
Transactions | Scope, send-via configuration, operation order | Commit, rollback, timeout |
Shutdown | Stop intake, cancel, drain, close | No abandoned or unbounded work |
For batching, use the SDK batch and add until TryAdd/tryAdd rejects the next message; a plain list checked before serialization is unsafe. Batch settlement is not universally atomic, so represent partial outcomes and retry item by item. Where code uses AMQP annotations or nonstandard sections, compare the modern SDK’s full AMQP message access with captured legacy messages.
Sessions create an exclusive lock and ordering boundary. Test selection, state, concurrency, renewal, abandonment, and restart. Microsoft’s Service Bus session documentation cautions that DLQ replay gets new enqueue and sequence positions, so it cannot restore original global order.
Broker transactions cover only supported Service Bus operations; external databases and providers are not enlisted. Microsoft documents cross-entity patterns, a two-minute timeout, and no automatic retry for a failed transaction scope in its Service Bus transaction documentation.
Preserve Settlement, Lock Renewal, Retry, and Dead-Letter Behavior
Peek-lock receiving gives the handler time-limited exclusive access, followed by one of several outcomes. Microsoft’s guide to transfers, locks, and settlement explains why a settlement call can fail even after business work has succeeded. That uncertainty is the root of many duplicate side effects.
Event | Broker result | Handler obligation |
Complete | Removed if acknowledgement succeeds | Persist success with an idempotency decision |
Abandon | Available for redelivery | Retain failure context; avoid repeated side effects |
Defer | Retained for sequence-number retrieval | Persist sequence number and owner |
Dead-letter | Moved to DLQ | Preserve reason, identifiers, and replay decision |
Lock expires | May be redelivered | Reconcile the prior side effect |
Process crashes | Settlement may not occur | Recover from durable business state |
Network drops after settlement request | Acknowledgement may be unknown | Expect redelivery; suppress duplicate effects |
Receive-and-delete | Removed on transfer | Use only when loss is accepted |
Configure lock renewal for the measured handler duration, not as a substitute for bounded work. Prefetch starts the lock clock before processing; raising prefetch can increase throughput but can also cause locked messages to wait until they expire. Set processor auto-completion, maximum concurrency, prefetch, lock renewal, retry policy, session concurrency, error callback behavior, handler cancellation, and shutdown drainage explicitly in both languages. Microsoft’s performance guidance for Azure Service Bus recommends reusing clients and tuning batching, prefetch, and topology with measured workloads.
Unexplained lock-lost growth, a handler that performs a side effect before establishing an idempotency decision, or a shutdown that terminates in-flight work without recovery evidence must stop promotion. Pause intake, inspect business state and delivery count, settle only when the outcome is known, and replay under a recorded operator decision.
Separate SDK Migration From the Move to Microsoft Entra ID
Microsoft recommends passwordless authentication with Microsoft Entra ID and Azure role-based access control (RBAC) where possible, while managed identities remove stored application credentials. That does not make identity a harmless add-on to the SDK change. A new SDK, new token source, new role assignment, and new network dependency in one release create four simultaneous failure domains.
Choose one of three paths deliberately:
Path | Use when | Main benefit | Exit requirement |
Modern SDK with existing Shared Access Signature (SAS) connection string temporarily | Semantic risk is high and test capacity is limited | Isolates SDK behavior first | Dated plan to migrate and remove secrets |
Modern SDK with Entra service principal | Workload runs where managed identity is unavailable | Central RBAC and credential governance | Rotation, secret/certificate controls, denied-access tests |
Modern SDK with managed identity | Supported Azure host and identity lifecycle are proven | No application secret stored | Role scope, token path, failover, and emergency access verified |
Use the narrowest applicable built-in role: Azure Service Bus Data Sender, Data Receiver, or Data Owner, scoped to the entity or namespace where practical. Test allowed and forbidden operations, token acquisition after restart, local credentials, every deployment slot or scale unit, and credential expiry. Microsoft’s passwordless connection migration guide and managed-identity guidance for Service Bus document the supported model.
Official guidance gives different propagation windows: the passwordless guide says assignments usually take one or two minutes and rarely up to eight; managed-identity guidance says up to five. Treat propagation as asynchronous and use bounded validation retries. When validating role removal, account for cached managed-identity tokens that may remain valid for up to 24 hours unless the application restarts.
Retain SAS only while a tested rollback needs it. After soak, prove removal from configuration, secret stores, deployment variables, local files, and break-glass procedures; disable local authentication only after every legitimate caller passes an Entra test.
Prove AMQP Connectivity Through Firewalls, Proxies, and Private Endpoints
Azure Service Bus uses AMQP as its primary wire protocol. Microsoft documents AMQP over TCP on ports 5671 and 5672 and AMQP over WebSockets on port 443; HTTPS on port 443 can also be needed for token acquisition and some management operations. WebSockets can traverse restrictive networks but add connection overhead, so transport choice should be measured rather than treated as cosmetic. Microsoft’s Service Bus transport and firewall guidance provides the supported port model.
Test from every real host class, including production subnets, scale sets, Kubernetes node pools, Functions plans, on-premises hosts, desktop networks, and recovery regions, rather than only from a developer laptop.
Test | Evidence | Blocking failure |
DNS | Resolved namespace and private-link names | Resolution differs from design |
TCP/TLS | Negotiated connection on required port | Firewall, proxy, rule, or inspection failure |
WebSockets fallback | Explicit proxy-path test | Upgrade blocked or excessive churn |
Token path | Entra token from workload identity | HTTPS, proxy, identity endpoint, or DNS failure |
Private endpoint | Route and private DNS proof | Traffic escapes publicly or resolves incorrectly |
Connection reuse | Stable connections under load | Per-message connections or port exhaustion |
Regional behavior | Latency and reconnect from both sites | Lock budget or throughput fails |
Failure injection | Controlled deny, DNS failure, proxy reset | Silent retry loop or unalerted backlog |
Do not hard-code namespace IP addresses discovered from DNS. Validate documented outbound paths, private endpoints, and TLS inspection explicitly.
Promote only after sustained send, receive, token-renewal, reconnect, and management tests pass from production hosts using the expected transport. A laptop-only pass, an unmeasured WebSockets fallback, or inconsistent private DNS across scale units blocks release. Recovery pauses intake before lock storms, restores the supported transport configuration, drains safely, and replays only after the path is clean.
Build Compatibility Tests for Ordering, Idempotency, and Transactions
The harness must run known fixtures through both implementations and compare broker-visible messages with business results. Version its tolerances so thresholds remain approved requirements.
Test family | Vary or inject | Required evidence |
Contract | Body, properties, subject, TTL, scheduling, replies | Byte/property diff and filter result |
Delivery | Duplicate send, redelivery, lock expiry, abandon | Stable IDs and one business outcome |
Ordering | Partitions, sessions, concurrent handlers | Sequence within the declared boundary |
Settlement | Complete, defer, dead-letter, uncertain acknowledgement | Delivery count, DLQ metadata, operator path |
Processor | Concurrency, prefetch, auto-complete, cancellation | No silent loss; bounded drainage |
Resilience | Restart, network, credential, dependency failure | Retry trace, backlog recovery, no poison loop |
Transactions | Commit, rollback, cross-entity operation, timeout | Broker state and compensation |
Performance | Peak rate, batches, large messages, latency | Throughput, latency, connections, throttling |
Recovery | Replay, session state, scheduled/deferred messages | Reconciliation and replay evidence |
The reason to emphasize backend idempotency and distributed-system skills is visible in an order-payment failure window. Assume the message has stable MessageId=pay:order-74219:v1 and the handler uses peek-lock:
1. The handler receives the message and begins a database transaction.
2. It inserts an idempotency record keyed by MessageId and effect type, posts the payment state, and marks the effect COMMITTED.
3. The database transaction commits.
4. The handler calls complete, but the network drops before the settlement acknowledgement reaches the client.
5. The lock expires and Service Bus redelivers the message.
6. The next handler finds the committed idempotency record, does not repeat the financial action, records servicebus_duplicate_delivery_suppressed_total, and completes the message.
7. An operator can prove the outcome from the idempotency row, message ID, delivery count, trace ID, settlement error, reconciliation result, and final settlement.
Configured duplicate detection can reject repeated stable MessageId values within its history window, but it does not remove the consumer failure window; Microsoft also documents a throughput tradeoff as the window grows in its duplicate-detection documentation.
Do not claim exactly-once processing: external databases and payment providers are outside the broker transaction. When idempotency state is ambiguous after redelivery, stop the consumer or session, reconcile the effect, then complete, replay, or dead-letter under an accountable decision.
Rehearse Parallel Operation Without Creating False Shadow Consumers
A second receiver attached to the same queue is a competing consumer: it removes messages from the pool that the original consumer would otherwise receive. It is not a passive mirror. By contrast, each topic subscription receives its own copy, subject to its filters, which makes a temporary cloned subscription a possible comparison path when filters, forwarding, sessions, retention, and cleanup are validated. Microsoft’s Azure Service Bus messaging overview describes this queue-versus-subscription model.
Workload | Safe rehearsal | Primary control |
Topic consumer | Temporary cloned subscription with equivalent filters | Compare outcomes; suppress side effects |
Queue consumer | Test namespace with approved captures | Sanitize data; preserve contract and order cases |
Queue with replay | Controlled copy to an isolated entity | Stable IDs, replay ledger, bounded window |
Producer | Durable outbox feeding both targets | Reconcile asymmetric publication |
Managed connector | Vendor-supported test connection | Prove version and transport |
Session workload | Isolated sessions or valid cloned subscription | Preserve session IDs and order |
Application-level duplication can be safe only when the duplication itself is durable. A dual write performed as two independent sends can succeed on one path and fail on the other, creating a reconciliation problem more dangerous than the original migration. Where dual publication is unavoidable, write one durable outbox or intent record, use stable identifiers on both messages, track per-target delivery, compare results, and define an explicit stop date.
For shadow processing, suppress irreversible actions and compare computed decisions, not just received counts. Validate filter matches, headers, session routing, dead-letter outcomes, latency, and ordering. A “shadow” that calls a live payment, email, fulfillment, or entitlement service is a second production executor.
Any comparison path that steals queue messages, creates irreversible duplicate actions, or cannot reconcile asymmetric sends must be disabled. Preserve the intent or replay ledger, drain only the isolated entity, and reconcile every unmatched identifier before resuming.
Roll Out by Producer, Consumer, and Namespace Risk Rings
A namespace-wide “big bang” removes fault isolation. Ring by role and semantic risk, and promote only when telemetry and business reconciliation agree. These soak periods are practitioner recommendations; extend them to cover real peaks and schedules.
Ring | Entry | Recommended soak | Promotion evidence | Rollback trigger |
Lab / controlled replay | Contract and target build complete | Full suite plus restart and failure cycle | No unaccounted message or business difference | Any contract or recovery mismatch |
Noncritical producer | Consumer compatibility proven | Four hours and one peak | Send, batch, and downstream parity | Missing, malformed, or asymmetric message |
Noncritical consumer / low-volume subscription | Idempotency and DLQ path proven | 24 hours or one business cycle | Settlement, backlog, and outputs match | Duplicate effect, lock loss, poison loop |
Session workload | Session and state recovery tests pass | One session cycle plus restart | Per-session order and state match | Ordering or session-lock anomaly |
Transactional workload | Broker transaction and compensation tests pass | One full business cycle with failure injection | Commit/rollback evidence reconciles | Uncertain or split outcome |
High-throughput / critical namespace | Capacity test and rollback approved | Two peak periods, normally 48 hours | Stable throughput, latency, throttling, backlog, and KPIs | Sustained degradation or drift |
Managed integration | Vendor evidence and isolated test complete | One real scheduled execution | Version, protocol, owner, and output proven | Missing proof or unexpected transport |
Each ring needs a release owner, business validator, timestamps, build/configuration hashes, dashboard, rollback decision-maker, and sign-off. Producers and consumers may move separately only when every coexisting old/new pairing is proven.
Rollback means restoring the last supported AMQP-capable build or pausing intake for drain and replay. At or after September 30, 2026, rollback never means SBMP. Stop rather than roll back blindly when the prior build is unsupported, side effects are ambiguous, schemas changed, or messages were partly processed.
Promote only after representative traffic, a restart, and a controlled dependency or network failure. Calendar pressure is not evidence, and no exception can authorize SBMP beyond the deadline.
Observe Semantic Drift, Backlogs, Failures, and Duplicate Side Effects
Infrastructure dashboards can remain green while business behavior diverges. Build one migration view that combines Service Bus metrics, protocol evidence, application traces, deployment data, and business reconciliation. The observability patterns in OpenTelemetry for backend observability are useful for trace correlation, but the migration also needs broker and domain-specific controls.
Signal group | Monitor | Interpretation |
Connections and protocol | Connections, reconnects, AMQP/SBMP mix, transport | Old callers or connection churn |
Service requests | Success/failure, server/user errors, throttling | Authorization, client, service, or capacity fault |
Queue health | Active/DLQ count, oldest age, message rate | Backlog growth or poison loop |
Processor behavior | Exceptions, lock loss, retries, duration, cancellation | Settlement or shutdown drift |
Performance | Throughput, latency, batch fill, prefetch | Approved capacity envelope |
Business integrity | Duplicate actions, missing records, order violations, reconciliation | Workflow meaning remains intact |
Deployment context | Build, configuration, identity, host, ring, time | Attribute changes accurately |
Propagate identifiers and trace context without sensitive payloads. Record when the business result becomes durable and when settlement is attempted. Alert separately on duplicate delivery and duplicate side effect; only the latter necessarily indicates a business defect.
A zero-SBMP chart must show its window, namespace coverage, diagnostic health, and expected executions. A flat DLQ is not healthy if consumers stopped and active backlog rises. Each dashboard tile needs an owner, query, stop threshold, and recovery action.
Block release for unexplained reconciliation differences, rising oldest-message age, ordering violations, sustained lock loss, or critical telemetry gaps. Recovery requires baseline backlog, reconciled ambiguous identifiers, accounted replays, and a clean protocol view.
Remove Legacy Packages, SBMP Rules, Connection Strings, and Exceptions
Decommissioning is a separate release phase. A modern deployment does not remove an old package from a shared library, delete a forgotten connection string from a secret store, or close a vendor exception automatically. Build a proof package that an auditor or incident commander can reproduce without relying on a project spreadsheet’s green cell.
Evidence domain | Required proof |
Source and dependencies | No direct or transitive legacy references; lock and central version files are clean. |
Built artifacts | Assembly/JAR, shaded package, image-layer, and software-bill-of-materials scans are clean. |
Runtime | Full-window telemetry shows no SBMP; every expected periodic workload ran. |
Network | Obsolete SBMP exceptions are removed; required AMQP/HTTPS paths are documented. |
Configuration | Old transport flags, package settings, and unused connection-string keys are removed. |
Authentication | Retired SAS policies, keys, connection strings, and secrets are removed after rollback closes. |
Operations | Dashboards, alerts, runbooks, templates, and support procedures reference modern clients. |
External dependencies | Vendor cases close with version and protocol proof; managed connectors are validated. |
Governance | Exceptions expire or become approved residual risks with owner and containment. |
Scan dependencies in continuous integration and the final artifact. Recheck deployed environments after rollback closes, including dormant machines, slots, desktops, and recovery images. Preserve credentials only until the supported rollback expires, then prove the retired credential fails.
Delete obsolete SBMP network allowances only after checking shared uses. Retire dashboards only after replacements work, and mark old runbooks so responders cannot restore an SBMP build.
Decommissioning closes only when two reviewers can trace every row to clean source and artifact evidence, modern transport, a supported build, a named owner, and closed credentials or exceptions. Unavailable binaries, unexecuted jobs, and unexplained connections remain open risks.
Build a Deadline-Relative Cutover and Post-Deadline Remediation Plan
Define T-0 as September 30, 2026, the official legacy-SDK retirement and SBMP cutoff. The plan below remains usable before the date, on it, and after it. Freeze unrelated messaging changes, use one migration command cadence, and maintain a single decision log. An organization starting after T-0 should treat every residual SBMP dependency as an incident and complete the omitted evidence gates rather than skipping directly to package replacement.
Window | Required work | Exit gate |
T-30 to T-22 | Inventory code, binaries, traffic, owners, criticality, sessions, transactions, and hidden integrations. | Every workload has an owner, protocol confidence, impact, and target. |
T-21 to T-15 | Build .NET/Java targets; freeze contracts; test behavior, identity, network, failure, and rollback. | Golden-message and recovery tests pass. |
T-14 to T-8 | Move low-risk producers, consumers, and subscriptions; validate Functions, adapters, connectors, and vendors. | Ring sign-offs and reconciliation are clean. |
T-7 to T-3 | Cut session, transactional, critical, and high-throughput workloads; exercise rare jobs. | Peak evidence, business approval, and supported rollback are recorded. |
T-2 to T-1 | Freeze unrelated releases; finish cutovers; rerun scans and protocol queries; remove obsolete access where safe. | No unknown owner, protocol, source, schedule, or vendor status. |
T-0: September 30, 2026 | Run final protocol checks, attestations, exception review, key decisions, and incident handoff. | Zero SBMP dependence and no unnamed legacy workload. |
T+1 to T+7 | Isolate residual workloads; migrate or replace them; reconcile ambiguous actions; replay safely. | Supported AMQP paths with no unexplained backlog or outcome. |
T+8 to T+30 | Remove obsolete secrets, rules, dashboards, and runbooks; close vendors; repeat zero-SBMP verification. | Complete decommission evidence and approved residual risks. |
For every migration or remediation decision, record the workload and entity, build and package versions, identity and network path, fixture and test results, observation window, protocol query, technical metrics, business reconciliation, approvals, rollback trigger, and final disposition.
Before T-0, use at least a daily decision cadence and increase it during the highest-risk cutover window. At and after T-0, any residual SBMP dependency should move under incident command. Engineering owns behavior; platform owns diagnostics and network; security owns identity and credentials; application owners own recovery; business validators own reconciliation; and the program lead owns cross-team escalation.
Pause promotion or operation for unexplained SBMP, unresolved source or vendor status, an unexecuted critical workload, a duplicate business effect, an ordering failure, unexpected DLQ or backlog growth, or an unsafe rollback. Recover through a supported AMQP build or a documented pause, drain, reconciliation, and replay path. SBMP is not an acceptable rollback at or after T-0.
The T-0 acceptance condition is not “migration work started” or “AMQP observed.” It is zero SBMP dependence, no unnamed legacy workload, supported builds for every active path, completed semantic and failure tests, verified identity and network routes, contained residual risks, and reproducible evidence. For a post-deadline remediation, closure requires the same proof plus reconciliation of every failed, delayed, or ambiguous business action caused by the residual dependency.
A successful AMQP connection proves only that one process reached one endpoint. Completion requires message bodies and properties to retain their meaning; ordering, sessions, and transactions to behave as designed; settlement and retry windows to be understood; duplicate side effects to be suppressed; network and token paths to survive failure; dashboards to expose backlog and semantic drift; and evidence to show that unsupported packages, SBMP, credentials, rules, and exceptions are gone.
Whether assessed before or after September 30, 2026, the question is the same: can the team handle replay, lock loss, restart, proxy failure, credential change, and ambiguous settlement without guessing? Fixtures, traces, reconciliations, named owners, and signed gates make the answer defensible.
The Refonte Learning APIs Developer Program is described as a three-month program requiring about 10–12 hours per week. Its verified coverage includes authentication and authorization, API testing, error handling and logging, versioning and deprecation, microservices, performance optimization, API security, hands-on projects, and mentor access. These foundations support disciplined integration work; the page does not list Azure Service Bus, AMQP, SBMP, or the named SDK migration, so product-specific coverage should be confirmed separately.
