Products · DLQ Manager
What's new
DLQ Manager ships continuously - every merged change lands here, newest first, described by what it does for you rather than how it was built. New here? Start with the product tour.
-
Counters that keep up with a burst, and say so when they do not
The background projection that keeps per-queue pending and archived counts used to recompute every queue it saw in every batch of changes - a 105,000-message burst across 150 queues meant a hundred thousand recomputes, counts that trailed the broker by tens of minutes, and in one case a queue shown as empty while it held 700 messages after a counter clean-up raced the recapture. It now marks the queues a burst touches and recomputes each one once per round, a few seconds apart, from a single snapshot query, so the counts describe one instant and are current seconds after the burst ends. Every counter write carries the version it was computed against, so the periodic clean-up and the live path can never overwrite each other's fresher number. And the worker now measures how far behind the writes each projection is - on its readiness page, as metrics, and behind an alert - so a late number is visible before anyone reads it. No message is ever affected by this; it is the display that was late, and it is not any more.
-
Run 14: the regression check after a week of rewrites
Fourteen runs into the stress-test program, the question was whether a week of changes to the write and access paths had cost anything. It had not: 105,000 banked dead-letters drained in 4 minutes 8 seconds at a 590-per-second peak, the same ~16.8 request units per message, zero loss, zero failed writes, 150 capture toggles fired twenty at a time all landing, and operator clicks at 0.2-0.3 s throughout - the automatic scale-out from two to four instances took about two minutes. Two ceilings were measured for the record: a single tenant's writes land on one storage partition, and a Standard Service Bus namespace throttles at about the same rate, so a tenant tops out near 600 captures per second - twenty times what a tenant is promised, and a Premium namespace and a larger partition budget away from more. The one finding, the lagging counters, became the entry above. The full record, with telemetry queries, ships with the product.
-
Independent review 5: one grant lifecycle for every writer, policy changes that take effect, a spending bound that holds
A fifth independent technical review of the onboarding batch found twelve issues, no cross-tenant exposure, and was answered the same day. Every writer of access - grants, invitations, the organization default, bulk removal - now shares one set of rules: the last administrator is kept, a revoked default stays revoked on every replica, an invitation is consumed before it grants and never broadens a scoped invite, and the identity it matches is the sign-in's user principal name only. Turning MFA for administration on and then off is judged on stored state. A settings change can no longer roll back a concurrent security change. The AI month is reserved before each call. The security checklist says unknown when it does not know. The response register and the review itself are published in the repository.
-
Invite a colleague by e-mail
Access management now takes a work e-mail address, a role and a scope, and the person gets exactly that the first time they sign in with Microsoft - nothing is granted before, and the grant is written against the identity Microsoft vouches for, never the address. Pending invitations are listed as "not signed in yet" with a copy-link (it opens the sign-in with their address filled in) and a withdraw. Only addresses in your own organization; a guest from elsewhere is granted by object id as before. Corrected 2026-10-12 after an independent review: a scoped invitation now yields exactly its scope (the organization-wide default is not added on top); the invitation is consumed before the grant is written, so a withdrawal always wins; the identity matched is the sign-in's user principal name and nothing else. No invitation e-mail is sent - the inviter copies the sign-in link.
-
Secure your workspace: five things to have in place before the first incident
A checklist appears in the menu while anything is open and leaves it when all five are done: a second administrator (the product refuses to remove the last one), MFA for administration, a namespace connected without a secret, an alert channel, and the first dead letter captured. Each item says why it matters and links to where it is done. It is judged from what is set up, nothing is stored, and it stays reachable from Help. Corrected 2026-10-12 after an independent review: an item the product cannot check is shown as unknown and keeps the list in the menu; the MFA item describes the switch, which enforces nothing by itself - the policy your Entra administrator binds to the context does.
-
A first run that asks three things
The first administrator of a new workspace is met by a short wizard: name the workspace, tick what you came for, connect a namespace - every step skippable, shown once. The goals you tick put suggestion cards under the empty Namespaces page, each a link into the real screen; they decide nothing else. The wizard can be reopened from Help at any time.
-
The AI budget shown as money
The monthly token budget in Tenant settings now says what it is worth - in SEK for Swedish, NOK for Norwegian, EUR otherwise - as an estimate included in your plan, never a separate invoice. A new workspace starts at one million tokens. Whatever a workspace sets, OpsChisel's own monthly ceiling per organization applies, so "no cap" can never run away. Corrected 2026-10-12 after an independent review: the month is reserved before each call, so concurrent requests cannot exceed the remaining allowance by more than one call's estimate. The amounts are estimates at configured prices and exchange rates.
-
Administration asks for your organization's step-up policy, when you want it to
A new switch in Tenant settings, "Require MFA for administration", ties granting access, changing namespaces and settings, and plan changes to a Microsoft Entra Conditional Access authentication context. Flip it on, bind a policy to the context in your Entra (MFA, a compliant device - your choice), and an administrator whose sign-in does not satisfy it is shown one clear prompt, signs in through the policy, and lands back where they were. The switch alone enforces nothing; your Entra policy does. Reading and operating dead letters never ask. Drilled end to end against a real Conditional Access policy before shipping. Corrected 2026-10-12 after an independent review: switching it on and off is judged on stored state, so it cannot be turned off without the context.
-
The plan you chose on the pricing page follows you into the product
Starting from Try it free, Starter or Pro on this site carries that intent through sign-in: the provider sees "asked for Pro (pricing)" next to the organization and the admit dialog pre-selects it. Nothing is granted by the choice itself. The sign-up confirmation now says what happens next and that nobody is charged by signing in.
-
Who can join: your organization decides what a new sign-in gets
Tenant settings gains "Who can join": nobody (the default - a colleague who signs in sees nothing until an administrator grants a role), or Viewer or Operator for anyone from your organization. The first grant a newcomer receives this way is marked as given by the organization's default and audited, so it is visible and revocable like any other. Corrected 2026-10-12 after an independent review: a default-role grant you revoke stays revoked on every replica, and an explicit grant reinstates; a person who already has access through a group or an invitation is not given the default.
-
Sign-up that cannot be used to flood a mailbox
The website's sign-up form carries a keyed visitor token from this site to the product, and the product keeps three budgets: per visitor, per recipient address per hour, and a ceiling per replica per minute. Past a limit the form says so and asks you to try later; a mailbox that already received its share this hour is not mailed again. Mail is best effort - "Continue with Microsoft" always works without it. The form has a marketing opt-in that is off by default and recorded with the request.
-
A payload the redactor cannot read is not sent to the model
Redaction now fails closed. A payload that looks like JSON or XML but will not parse, an XML document with a DTD, or a payload nested deeper than three serialized levels is omitted from the prompt outright - the diagnosis works from the metadata and properties instead. The tolerant recovery grammar introduced on 2026-10-09 is retired: an independent review showed its grammar was narrower than the parser's, and every gap was a secret leaving with a "redacted" label on it. Corrected 2026-10-12 after an independent review: a comment before the document, or a document quoted inside a string, no longer bypasses structural redaction - both are redacted by field name.
-
Queued bulk work carries your identity and resolves your grants when it runs
A resend, archive or delete that runs in the background carries the roles and groups your sign-in had when you started it, for the batch's lifetime, and your stored grants are re-resolved as each batch executes (through a permission cache of up to a minute). A stored grant revoked between the click and the batch confers nothing. Nothing is granted on the way through the queue; the background actor stays you, for the audit trail.
-
Payload clean-up that cannot delete a body a capture just reused
The orphan sweep deletes only the exact version of a blob it listed, so a content-addressed body a concurrent capture re-uploaded in between is left alone and counted; a blob without a version is never deleted. The sweep now pages through storage under a time budget and resumes where it stopped, so a large store is cleaned in bounded slices. Grace before a blob is judged is a week.
-
An organization keeps a working administrator; a blocked organization is cut off live
The last administrator grant can no longer be revoked, demoted or given an expiry while it is the only one - grant TenantAdmin to someone else first; a group that holds TenantAdmin counts as an administrator route too. Blocking an organization now drops its live connections and refuses anything they ask for next, stops its capture on every replica, and the client is told why. An organization the registry does not know is not treated as blocked. Corrected 2026-10-12 after an independent review: removing all of a person's grants, and invitations, respect the last-administrator rule too; an organization blocked after it queued work has that work refused when it comes up for execution.
-
Only a person signed in through the app can become the first administrator
An application token - even one carrying a different scope - is refused on every user path, including live connections. The issuer of a token is bound to the token's own organization in every admission mode. An operator's admit or block that races a first sign-in is re-applied onto the fresh record instead of failing.
-
The provider console shows each organization's own counts
Namespace and entity counts per organization in the provider console now come from that organization's configuration; they used to repeat the operator's own.
-
Sign up from the website with two fields
The website's form takes a work email and a company name and nothing else. The email's domain tells DLQ Manager which Microsoft Entra organization you belong to, the organization is registered before anyone has signed in, and you get the sign-in link by mail. Consumer mail addresses are turned away with a plain reason; a domain no organization has verified becomes a conversation with us rather than an account. The endpoint behind the form is keyed, rate-limited per address and ignores bots quietly.
-
A blocked sign-in says exactly what to do next
When your organization's Entra policy requires an administrator to approve DLQ Manager, the page now leads with the cheapest way out - Microsoft's own Request approval button when your tenant offers it - then the ready-made approval link to copy or mail, then sign in again. It also states what the administrator is approving: signing in and reading your own profile, and acting as you towards the DLQ Manager API. No directory read, no access to your Azure resources.
-
The first person from your organization to sign in becomes its administrator
No more asking an Entra administrator to assign an app role before anyone can start. The organization's first sign-in gets the tenant-administrator role when nobody holds one yet, claimed through a one-per-organization marker so two simultaneous first sign-ins can never both win, written to the audit trail and shown in Access management as the workspace owner - revocable like any grant. An organization that prefers to pre-decide its administrator still can: an Entra app role on the first sign-in wins and nothing is written.
-
Organizations waiting: admitted with their plan in one click
The provider console lists every organization that signed in and is waiting, with who knocked and when. Admit opens the plan dialog so the tier and length are chosen in the same click; the person's waiting page lets them in within thirty seconds and they get a you're-in mail. Block refuses an organization at sign-in with a reason and deletes nothing; recent decisions can be undone from the same page.
-
Admitting an organization no longer needs a deployment
Admission is now a record, not a configuration file: an unknown organization that signs in is either admitted on the spot, queued for a one-click approval, or refused, by policy. A queued organization waits inside the product - signed in, on a page that checks every thirty seconds and opens the door by itself the moment it is admitted - rather than on an error page or in a mailbox. The static allow-list remains as a hard allow for the organizations already in.
-
A lapsed trial says so, everywhere
When a trial has ended, every page carries one banner that names the date and what still works, every refused action explains itself in the same words instead of reporting an outage, and Plan & usage shows Trial ended with the plan cards right below. A plan limit that is reached reads as a plan limit, with the way to Plan & usage, not as the backend being unreachable.
-
A lapsed trial pauses capture and changes; retained records stay available within their retention
An organization whose trial has ended, or whose subscription is suspended or cancelled, keeps what it captured within the plan's retention period and can browse and export it. What stops: capture - the listeners are halted on every replica and dead-letters stay in your own queues - and every change: resend, archive, delete, rules, automation, adding anything. Choosing a plan, cancelling, removing a namespace and leaving stay open, and a plan becoming active restarts capture within seconds. Bounded background work that was already running completes. Before this, an expired trial changed nothing at all. Corrected 2026-10-12 after an independent review: retention is finite - the plan's period - and this entry said otherwise.
-
Approvals for departments, honest job completion, one capture per delivery
A department approver who holds the right through a namespace group can now open the approvals page and sees that department's requests - never another's - without a tenant-wide role. Approved cleanups of a vanished subscription run (the gate had compared two spellings of the same path and refused them). A signed recapture the broker delivers twice after a crash is recorded once, with no second delivery count or alert. An export or purge worker that loses its lease publishes no completion marker and stops a purge within one delete; the job record is the only statement of completion.
-
Every retained body in the export, and a History tab that opens them
A tenant export now inlines every body a record references - the current one and every retained prior body under its hash - and lists any reference the store could not serve, historical or current, so you can see exactly what an export is missing. Download and validate your export before purging the workspace: purge removes the server-side export as well. The message dialog's History tab states per delivery whether the body it carried is available and opens it on demand, with the hash, length and encoding recorded at capture; the route needs the same two permissions as the current body.
-
Redaction that reads broken payloads the way the parser would
Superseded on 2026-10-11 by fail-closed redaction: the tolerant grammar described here is retired, because its grammar was narrower than the parser's. Kept for history. A payload that looks like JSON or XML but will not parse is now redacted by a small tolerant grammar instead of patterns: a sensitive field's whole value is masked - nested objects and arrays, nested elements, escaped names, values the input ends inside - and comments and processing instructions are removed. A payload serialized inside a string field, the commonest envelope shape, is redacted by field name too. The four inputs that leaked in our third review and nine more are the regression set.
-
Immutable, content-addressed payload storage
Oversized and retained message bodies are stored as immutable, content-addressed blobs under their record, so a write that loses a race never touches the bytes a committed record points at. A body that cannot reach storage fails the capture and is retried by the broker instead of being dropped. Deleting a record removes every blob it owns, and orphaned blobs are collected by checking the record that owns them - never by age. Bodies live within the plan's retention period; a 2026-10-11 change closed a reuse race in the clean-up. Each delivery records the encoding its body was stored with.
-
Live sessions end when the sign-in does; alert routes re-read every pass
A real-time connection now closes when its token expires and refuses every request from an expired session, so an expired tab cannot re-join a namespace's live events after its lease was removed; the console shows the sign-in-again prompt instead. Alert delivery re-reads rules, channel ownership and department membership on every delivery pass rather than from a minute-old cache.
-
Access edits that fail safe
A department deletion that is refused now changes nothing - grants, rules, channels and the audit trail stay exactly as they were. Retrying a half-finished move only completes it when the destination holds the exact grant the move intended, expiry included; anything else is a conflict, never a silent downgrade. Editing a namespace group requires the version it was opened at, so an old client can no longer restore a namespace another admin removed. Permission-cache entries record the generation they were built under and are never served after an invalidation.
-
Exports you can restore from, jobs that stop when they lose the lease
Archived audit weeks are copied byte for byte and their row counts come from decompressing the copy, so the export's hashes describe a restorable file. Each export job writes under its own attempt folder, with the manifest and a completion marker last, so two exports never collide and a crash cannot leave a partial export looking complete. An export or purge worker renews its lease on its own clock and stops the moment another worker has taken the job - it never publishes a result it no longer owns. Export parts are bounded by size as well as rows and one export runs at a time per process.
-
Approval counts that mean what they say
A four-eyes request now counts exactly what execution will touch, snoozed messages included, so a selection that needs approval can always be requested. Removing a vanished entity is its own approved operation that counts pending and archived messages together, and the request can be filed straight from the namespace page.
-
Redaction that holds on broken payloads
Superseded: replaced by the tolerant grammar on 2026-10-09 and then by fail-closed redaction on 2026-10-11. Kept for history. A payload that looks like JSON or XML but will not parse - the ordinary shape of a dead-letter - is now redacted by field name on the raw text before the value patterns run, and XML comments and processing instructions are removed. The three inputs that leaked in our second review, and four more, are the regression set.
-
A reused message id never joins another message's history
Capture no longer merges a stranger into an existing record on the strength of a matching producer MessageId: the same broker delivery received twice is ignored, and a producer reusing an id gets an independent record. Prior message bodies are now stored by content hash - identical bodies share one copy, bodies above the inline budget move to overflow storage instead of being dropped, and the record always says whether an earlier body is available, in storage, or not retained.
-
A tenant export you can restore from
An export now carries everything it points at: message bodies that had overflowed to blob storage are written back into their rows, archived audit weeks are bundled alongside the live audit, and a manifest lists every file with its hash and row count, what was inlined, what was redacted and anything that could not be included. Taken before a purge, the export is the complete copy it was always meant to be.
-
Export and purge jobs survive a crashed worker
A tenant data job now runs under a ten-minute lease that every progress update renews. If the worker that held it disappears, the next delivery finds the lapsed lease and finishes the job; a delivery that arrives while the lease is live comes back when it could have lapsed instead of being thrown away. A job abandoned three times fails with a clear message rather than showing Running forever.
-
Lineage you can trust, and originals that survive a fix
Our October review found two gaps in evidence handling and both are closed. A resend now carries a signature only this installation can mint, so a producer who knows a record id can no longer attach it to a message of their own and have it merged into that record's history - capture accepts the lineage only with a valid signature. And when an edited resend dead-letters again, the earlier delivery keeps the body it carried, with its hash and length, so the original is retrievable for as long as the record lives.
-
Immutable transformation versions and audited rule changes
A saved transformation version can no longer be overwritten: two editors who compute the same next number both keep their work under different numbers, and a resend pinned to a version always resolves to the steps that ran. Every monitoring and auto-remediation rule save or delete is now in the audit trail with who did it, the scope and the destination host - never the webhook itself.
-
Live views stop when access does
A real-time subscription is now a lease: every thirty seconds each open connection is re-checked with the same permission that admitted it, a subscription that no longer passes is removed and the page is told, and a connection whose sign-in has expired is dropped. An idle tab stops receiving a namespace's events within about a minute and a half of the grant being revoked.
-
Department admins get their pages
An admin who holds Namespace Admin only through a namespace group now sees Access management, Monitoring and Remediation in the menu and can open them: each page lists what they may see and nothing else. No tenant-wide role is needed to make the console work, so departmental isolation stays intact.
-
Access changes that cannot be undone by accident
Editing a namespace group now carries the version it was opened at: a stale dialog that would silently restore a namespace another admin removed is refused with a reload prompt. A permission lookup that was in flight when a revocation landed is never cached. The access matrix no longer shows expired grants as effective. A department move that failed halfway is finished by retrying it. And "Remove all access" is now "Remove direct grants", saying plainly that access through Entra groups must be changed in Entra.
-
Redacted AI prompts redact by field, not by pattern
The redacted-body scope now parses JSON and XML and masks every field whose name is sensitive - password, token, key, personal identifiers - whatever the value looks like, so a short password never survives on the strength of a value pattern. The dead-letter reason, labels and telemetry targets get the same treatment, and a redaction stage that cannot finish yields a placeholder rather than the input.
-
A filtered delete is never a whole-entity delete
Three fixes to destructive operations from our October review. Whole-entity partition deletion is inferred only from a request that selects nothing at all, with a check that treats any filter it does not know as a filter. The four-eyes approval threshold now counts exactly the set a sweep will touch, snoozed messages included, and removing a vanished entity goes through the same gate. Targeted topic resend is on by default for every tenant that never opted out.
-
Role names cannot revive privileges; department channels re-checked before every send
Deleting a custom role is refused while anyone still holds it, and a role confined to one namespace confers nothing outside it whatever an old assignment says - so a reused name can never hand tenant-wide rights to a dormant grant. Alerts that route to a department's channel are re-checked against current group membership when rules are evaluated and again immediately before each send, so a namespace joining a group later never posts into another department's Teams. A group cannot be deleted while a rule outside it still sends to its channel.
-
Saved channels: who may send, who may edit
A department's channel takes only rules whose namespaces are all inside that department - a Membership rule never posts into Company's Teams, even when the two share a namespace. A tenant-wide channel is usable by every department and edited only by a tenant admin. Channel deletes are audited, on-call addresses are show-once like webhooks, the scope picker offers only what you may create, and the id you are about to create is shown while you type.
-
Deleting a department cleans up after itself
Removing a namespace group now also removes the alert rules and the saved channels that belonged to it - rules first, so no channel is ever pulled from under a rule that still sends to it - and the audit row records how many of each went. The admin guide gained a step for setting up a department's own alert channel, end to end.
-
Saved channels: define "Membership Teams" once
A notification destination can now be saved under a name and owned by a department or the whole tenant. Rules point at the saved channel instead of carrying their own webhook, so rotating a credential is one edit and every rule follows. A department's admin manages the department's channels and can use the tenant's shared ones, never another department's. A channel cannot be deleted while a rule still sends to it, a rule whose channel is gone shows as paused rather than failing silently, and every channel change is in the audit trail.
-
One alert rule per department
Monitoring and auto-remediation rules can be scoped to a namespace group. One rule - Membership, dead-letter arrival, the department's Teams channel - covers every namespace in the group today and every namespace added to it tomorrow, with no rule to edit. Two groups sharing a namespace and a channel still produce one alert, and a tenant-wide rule keeps firing alongside: a department's rule adds a recipient, it never silences anyone. The department admin creates and manages it; the Monitoring page shows it as a single row at group scope.
-
Department access guide: migrating older Entra assignments
Following our second review of the day: the admin guide now says plainly that a security group assigned to the app with a product role before the Member role existed stays tenant-wide until that assignment is switched, and which audit row is the authoritative record of a group's membership changes.
-
A new Entra app role that grants nothing - on purpose
Entra requires a role whenever a security group is assigned to an application, and every DLQ Manager app role is tenant-wide inside the product. Following the department guide to the letter could therefore hand a whole department tenant-wide access by accident. The API registration now carries a sixth role, Member - access via namespace groups, that confers nothing: pick it when assigning a department's group so the group rides in the token, then grant the real access on the namespace group inside the product. The grant dialog warns, the roles help explains, and the guide names it the one rule to keep. Creating a namespace group whose derived id already exists is now refused instead of silently replacing the other group, and every membership change is audited with the namespaces added and removed.
-
An honest answer to "how fast does a revocation apply?"
Immediately on the replica that made it and within 60 seconds everywhere - the documentation, the code comments and the product page now all say the same thing, and removing someone from an Entra group takes effect at their next sign-in. Under the hood: expired permission-cache entries are evicted instead of accumulating, a token that could not list all of a user's groups never shares a cache entry with one that could, and object ids pasted in any letter case are stored and matched consistently.
-
A shared namespace no longer reveals the other department
Our technical review found two edges in the new department model and both are closed. A namespace that sits in two groups let one department's admin see the other group's members and grants; now they see only their own side, with a count of what is not visible. And moving a person between groups could silently overwrite a role they already held on the target; the move is now refused with a clear message instead, and nothing is lost.
-
Access by department, documented end to end
A new admin guide walks through department access in three steps - one Entra security group per department, one namespace group per department, and a role granted on the group - plus the day-to-day table: who can see a department, how a person moves, how to offboard someone, how to time-limit access, and how to delegate a department's own administration. The in-app roles help and the FAQ follow suit.
-
Time-bound access, and every revocation in the audit trail
A grant can now carry an end day: it stops conferring anything at the start of the next day and shows as expired until it is cleaned up - the right shape for a contractor or an incident war room. Revoking, moving someone between departments, removing all of a person's access and deleting a group now write audit entries with the role and scope that was removed. And when a namespace leaves the product, its grants leave with it, so a namespace added back under the same name starts clean.
-
Namespace groups: give a department its namespaces, not a list of grants
Access management has a new tab. A namespace group is a named set of namespaces - one per department - and a role granted on the group covers every namespace in it, the ones it holds today and the ones that join later. Grant on a group from the Grant access dialog or the onboarding wizard, see who holds what per group (inherited roles and the direct exceptions on single namespaces), move a person's grants to another group in one step, and remove every grant a person holds from the overview. Keep the department's people in an Entra security group and a department move becomes a single change in Entra. Granting on a group is delegated the way namespaces are: whoever administers every namespace in it can manage its people.
-
Hardened onboarding preview and transformation patterns
Two findings from our September security review, closed the same day. The namespace preview now applies the same host rule as adding a namespace before it opens any connection, so a private address or a look-alike domain in a connection string is refused up front. And pattern-based transformation steps run in guaranteed linear time with a fixed budget per step, so one tenant's pattern can never tie up shared capacity during a bulk resend.
-
Custom role names can never collide
A custom role name is now a plain identifier - letters, digits, spaces, dashes, underscores and dots. The review found that a name built from special characters could map onto another role's stored record and replace it, which would have let a namespace administrator rewrite a tenant-wide role. That door is closed; existing roles are unaffected.
-
A customer tenant's namespace is only ever reached through the Connect app
Passwordless namespaces in your own Entra tenant are connected with a token issued in your tenant to the OpsChisel DLQ Manager Connect app - never with the platform's own identity. A deployment without the Connect app configured now refuses a customer-tenant namespace outright rather than falling back, and the platform's own Service Bus namespaces can never be registered as a monitored namespace by anyone.
-
Your telemetry is read with your tenant's own credential
The Consumer tab and the assistant read your consumer's exceptions from the Log Analytics workspace you link to a namespace. That workspace is now queried with a token issued in your Entra tenant through the Connect app, so it can only ever return what you granted - never another customer's workspace, whatever id is typed in. Grant the Connect app Log Analytics Reader on the workspace; nothing else changes.
-
Passwordless onboarding from your own tenant, in three steps
The add-namespace wizard now walks a customer through the passwordless path end to end: grant the OpsChisel DLQ Manager Connect app consent in your tenant, assign it Service Bus data roles on one namespace with a Deploy-to-Azure button or a copyable script, and tell us the host. No connection string, no secret on either side, and you revoke in your own portal at any time. The optional telemetry link uses the same service principal.
-
Cross-tenant access without a single secret
Connecting a namespace that lives in your tenant to a service that runs in ours used to be the hard part of passwordless. DLQ Manager now uses a multi-tenant Connect app whose only credential is a federated trust in our managed identity: no password, no certificate, nothing to rotate or leak. The customer assigns ordinary Azure roles to the app in their tenant and the product presents a token issued there - and only there.
-
Self-hosted licensing that fails safe
For customers who run DLQ Manager in their own Azure subscription, entitlement is now a signed license document verified offline: a 30-day lease, a 14-day grace period with a banner, and then a restricted mode that keeps browsing and export working while capture and resend pause. Data is never deleted by a license state, tampered or forged documents are refused, and a clock set backwards cannot reopen a lease.
-
No platform-wide ceiling on monitored entities
Your capacity is yours. Limits on monitored entities are set by your plan alone; there is no shared platform quota that another customer's growth could consume. Capacity is protected by scaling the capture pump and by per-tenant circuit breakers, not by a global cap.
-
Swedish and Norwegian, verified on screen
The console and the message dialog were rendered in English, Swedish and Norwegian with real captured data and read screenshot by screenshot. Both translations are now at full coverage, the message dialog shows the same localized status words as the grid, and a layout fault that made the search box tower over the toolbar is fixed.
-
Watch a whole-entity resend, archive or delete happen
Start a resend, archive or delete across an entire entity and a live banner follows it - processed so far of the expected total, failures as they occur, and the per-message report one click away - until it closes with a final count. No more guessing whether a big operation is still running.
-
Every screen loads the way the landing page does
Monitoring, Trends, Access management and the plan page now show the shape of their real content while it loads instead of a bare progress bar, and tell assistive technology that the page is busy. Small, but it is the difference between a console that feels finished and one that flickers.
-
The messages toolbar fits a narrow window
Search, filters and saved views wrap cleanly on a tablet or a split screen instead of overflowing sideways; wide screens keep the same layout as before.
-
Trend charts readable without colour
The dead-lettered, resent and archived series are now told apart by line style as well as colour, the legend carries the same styles, and a screen reader gets a description of what the chart shows and the highest value on it.
-
Honest feedback on bulk operations
A whole-entity resend or delete runs as a queued operation, and the console now says so: "started" when it starts, with the per-message report one click from the notification, and the grid refreshing live as batches complete. Bounded selections still confirm completion and carry the same report link.
-
Every error tells you what to do next
Every screen now surfaces a failed load the same way: a permission problem says which administrator to ask, an expired session offers sign-in, an unreachable namespace explains how to reconnect, and anything transient offers a retry. No raw exception text, and no screen that pretends a failed load was an empty list.
-
Large replays finish in a fraction of the time
Bulk resend and archive used to work through a backlog one message at a time. They now process each batch in parallel, the way bulk delete already did - in our stress rig a resend that crawled at a handful of messages a second now clears well over fifty, so recovering from a big incident is minutes of work, not an afternoon. Every per-message outcome, duplicate guard and edit-lock is unchanged.
-
Wide namespaces capture at full speed
A namespace with hundreds of entities no longer shares the small capture budget meant for a handful of queues. The pump now sizes its in-flight work to the number of active listeners, so a large fleet gets the concurrency it needs while a small one keeps a healthy floor - measured capture across a 150-queue namespace rose several-fold with nothing to change on the customer's side.
-
Live dashboards can't quietly stall
The background worker that keeps counts, trends and alerts current now runs every batch under a hard time budget and reports its own freshness. A single slow call can no longer freeze the projections in silence; a stalled worker fails its health check and is restarted automatically, so what you see on screen is always moving.
-
Onboarding asks exactly what to capture
Adding a namespace now offers a clear choice - capture every entity starting now, only the ones that appear later, or nothing yet - with a preview of what was found (queues, topics, subscriptions, and the session entities that cannot be captured) and how much of your plan it uses. Namespace pages gained one reviewed Capture all / Stop all action, and making a topic resend-safe stays a separate, deliberate step. Capture is always read-only on the broker.
-
Ask the assistant why a message dead-lettered
An opt-in AI assistant explains a dead-letter in plain language - poison payload, schema drift, a downstream outage, throttling, an auth failure, a duplicate, or a broken consumer - and tells you how confident it is. It is on-demand only and never in the capture path, it runs against your own OpenAI-compatible endpoint (Azure OpenAI, Azure AI Foundry, or a model you host), sensitive fields are redacted before anything leaves, and every call is budget-capped and audited.
-
The consumer's real exception, next to the dead-letter
Link a namespace to your Application Insights and the message dialog shows the actual exception the consumer threw - type, message, top stack frames and the failed dependency, say an HTTP 503 to a downstream API - matched to this message by its trace id. You stop guessing whether the payload or the consumer was at fault, and the assistant reasons from the same evidence.
-
Know how a message really failed
Messages that exhausted their delivery attempts are now sorted by how they failed - a crashing listener, expiring locks, quick abandons, or slow retries - read from the delivery count and timing. It becomes a column, it splits failure clusters apart, and it drives both the guidance and the assistant's diagnosis.
-
See what makes one message different from its siblings
A deterministic payload check - no model involved - learns the shape an entity normally sees and lists exactly what is off about a failing message: a missing field, an unexpected null, a changed type or date format, an unknown enum value, an empty or double-encoded body. It is the fastest way to spot the one malformed message in a cluster.
-
The product remembers how you fixed the last one
Every successful edit-and-resend is remembered against its failure cluster - which fields you changed, with the values redacted. The next matching message offers what worked before as a one-click starting point, so a recurring fault gets faster to clear each time.
-
A message's whole story, in order
A timeline tab lays out everything that happened to a message in sequence - enqueue, each delivery attempt and how it failed, the dead-letter, any triage, the edits and resends, and the bulk operations that touched it - and shows whether its failure cluster arrived as a sudden burst or a slow trickle.
-
Explain a whole cluster and hand off an incident note
One action summarises an entire failure cluster from a sample of its messages and the evidence around them, and produces a shareable incident note you can drop straight into a ticket - so whoever picks up the pager gets the story, not just a count.
-
An alert the first time something new breaks
A monitoring trigger fires once when an entity starts dead-lettering in a way it never has before - a new reason, or the same reason failing in a new pattern. The alert carries a sample, how that entity used to fail, the listener hint and the next step, so a genuinely new problem stands out instead of hiding in the usual volume.
-
Point operators straight at the fix
Wherever an entity is dead-lettering because its consumer crashes or hangs on a payload, the product now says so - on the namespace page, in the message dialog, on cluster tooltips, in the alert body and in the assistant's answer - and links to the small code change that dead-letters a poison message cleanly instead of retrying it forever.
-
A one-line client library for honest dead-letters
A small client package wraps a Service Bus processor handler or an Azure Functions catch block so a crashing message is dead-lettered with the exception type as its reason, the message as its description and the stack as properties - while transient faults still retry. It preserves the trace id, so the consumer-exception link keeps working end to end.
-
Reshape a payload before you resend it
Named, reviewable transformations can rewrite a message before it goes back out - set, remove or rename JSON fields, replace text by pattern, adjust application properties, label or content type. You preview against a real dead-letter, every save is a new immutable version, and the resent message records exactly which version was applied.
-
Four-eyes approval for the big operations
An administrator can set a size above which a bulk resend or delete must be approved by someone else. The request carries a fresh count, a sample and a justification; a different person approves and executes it; and the whole exchange is captured as an exportable evidence pack - so a large, irreversible action is never one click by one person.
-
Triage a message or a cluster
Assign an owner, acknowledge, snooze or note any dead-letter, and attach an owner, a runbook and an acknowledgement to a whole recurring failure cluster - so a shared pile of dead-letters can be worked like an actual queue.
-
Operations figures worth reporting
A trends view now shows the numbers a team gets asked for: how many dead-letters were resolved by resending or archiving, the mean time from capture to resolution with its distribution, and a backlog-by-age table - built from daily rollups so the page stays fast.
-
See stuck consumers before the queue backs up
The live view behind the stalled-consumer alert shows which entities have messages that are not moving, since when, and which are building toward an alert - the earliest possible warning that a consumer is down or wedged, well before a queue overflows or messages expire.
-
Every release is signed and accounted for
The build pipeline now refuses known-vulnerable packages, committed secrets and high-severity code findings, publishes a bill of materials for both source and container image, and gives every image a keyless cryptographic signature. Deployment refuses any image this pipeline did not sign, and production ships only from the main line behind a dated confirmation.
-
Grant access by group, and roles scoped to a namespace
Roles can be granted to an Entra security group - so access follows your existing joiners-and-leavers process - and custom roles can be scoped to a single namespace. Going over your seat count fails closed rather than quietly letting extra people in.
-
Take your data out, or have every trace removed
A tenant can export everything held about it as line-delimited JSON, one file per store, streamed in parts as a background job with per-store progress. Deletion is the mirror image: it stops capture, cancels billing with credit for unused time, sweeps every store including archived audit and past exports, then re-counts each one and reports done only when nothing remains.
-
A plain data-handling disclosure
A data-handling and privacy page, linked from the footer, states where customer data lives, how it is encrypted, who the sub-processors are and what leaves the platform - in language a security reviewer can actually use.
-
Self-serve billing, live
Billing runs through Stripe with passwordless secret handling: start a subscription from hosted checkout, and change plan or cancel from inside the product, with prorated upgrades, cancel-at-period-end and clean re-subscription. The same seam also accepts Azure Marketplace, so a customer can buy through their existing Azure agreement.
-
No shared keys inside the platform
The real-time backplane now authenticates with the application's own managed identity and its access keys are switched off - joining storage, the command bus and the secret vault, which already run keyless. There is no shared connection string left to leak.
-
A support commitment you can read before you buy
Each plan now carries a published support commitment - response targets by severity and tier, with business hours stated - so the level of help you get is part of the plan, not a surprise after signing.
-
Versioned releases
The product now ships with real version numbers, starting at 1.0.0. The footer shows the build you are on, and the places that used to say a fix was on the way now close the loop against a version - so shipped means something specific.
-
Send feedback without leaving the app
A feedback button in the app bar files a bug, idea or question and quietly attaches the context that makes it actionable - your plan, the version you are on and the id of the last failed request - straight to our inbox.
-
The platform watches itself
A pack of always-on health alerts covers the signals that matter - server errors, latency crossing its target, error bursts, the background worker going quiet and sustained throttling - each routed to an on-call channel, so we hear about trouble before you have to report it.
-
One less key in production
The application now reaches its own storage through its managed identity, and the last storage account key was removed - one fewer secret to hold, rotate or lose.
-
Production-scale performance receipts, refreshed
A full production-shaped load session is now in the published stress-test record: 230,000+ dead-letters captured with zero loss and zero database throttles, dashboards answering in ~20 ms during a 450-message-per-second drain, and a rehearsed runbook for burst-scaling storage up and back down at zero extra cost.
-
One question, asked once
On multi-instance deployments, the routing-filter safety prompt could reappear for a topic that had already been secured moments earlier. The stale answer is no longer cached - the question is asked exactly when it matters, exactly once.
-
Production-shaped test environments on demand
The deployment template can now stand a full production-grade data tier (dedicated throughput, priority-based execution, burst-scale storage features) side by side with an existing environment - and hand everything back untouched when testing ends. It is how we load-test what we sell.
-
Early warning when consumers fall behind
A new consumer-lag monitor watches the age of the oldest waiting message per entity - alerting when processing falls behind long before queues overflow or messages expire.
-
The audit log scrolls forever
The audit trail now loads continuously as you scroll - no page buttons, no losing your place in a long investigation.
-
Backup and per-tenant recovery, by design
The recovery story is now documented end to end: point-in-time restore decisions, a safe restore-to-the-side runbook, and tenant-scoped recovery that can extract exactly one customer's data - never a blind overwrite.
-
Content Security Policy: enforcing
The console's full Content Security Policy moved from report-only to enforcing after a clean observation period - browsers now refuse any script the application did not ship.
-
Background checks coordinate across instances
The periodic monitors (stall detection, topology discovery) now elect a single worker per customer across all service instances - no duplicated probing of your Service Bus, no wasted calls, identical behavior at any scale.
-
Stall alerts that respect your attention
A stuck consumer now raises one alert per episode - with a reminder only if it stays stuck - and re-arms automatically on recovery. No more identical notifications every few minutes for a problem you already know about.
-
Stall detection is now yours to configure
Active-message stall monitoring joined the rule editor: pick entities, set the sensitivity, choose the channels - the same workflow as every other notification rule.
-
Stall detection wired end to end
The stall-detection engine now runs as part of the monitoring pipeline, from periodic probe to delivered notification, on the same at-least-once delivery rails as every other alert.
-
Stall probes that know your consumers
The stall monitor probes each entity with a lightweight peek and evaluates it per tenant - built to run continuously against production namespaces without disturbing them.
-
Durable memory for stall detection
Stall detection keeps its per-entity observations in durable storage - deployments and restarts never reset what the monitor has learned about your traffic.
-
Stall sweeps count before they peek
The stall sweep checks message counts first and peeks only where something could actually be stuck - continuous monitoring at a fraction of the Service Bus API cost.
-
Small fixes in the allowlist editor
The webhook allowlist's add button now sits where your eyes are, and an invalid webhook URL explains exactly what is wrong instead of failing generically.
-
Stall evaluation as a pure, testable core
The logic that decides "this consumer is stuck" is a fully deterministic, exhaustively tested unit - the judgement calls in your alerts are auditable, not heuristics buried in infrastructure code.
-
A discriminator for genuinely stuck consumers
New detection core that tells a genuinely stuck consumer apart from one that is merely slow or bursty - by watching whether the messages at the front of the queue actually change over time.
-
A single storage abstraction, all the way down
The final layer of the legacy storage stack is gone; what remains is exactly what production uses. Less code to audit, nothing dormant to misconfigure.
-
Retired the legacy staleness monitor
An unused single-tenant monitoring path was removed outright - superseded by the modern stall detection and metrics readers that replaced it.
-
Removed twelve dormant fallback implementations
Every disabled placeholder from the single-tenant era is gone. If a capability exists in the product, it is the real, multi-tenant implementation - there is no degraded mode to accidentally run.
-
The control plane is unconditionally cloud-native
The configuration layer now runs exclusively on the multi-tenant database - the legacy toggle and its untested fallback path no longer exist in the codebase.
-
Retired the legacy migration tool
The one-shot migration utility from the single-tenant era served its purpose and left the codebase.
-
One search and message store, not two
Message storage and search run exclusively on the modern engine; the legacy blob-and-search pair was deleted rather than left dormant.
-
Dead configuration keys removed
Legacy API-key settings that no deployment used anymore are gone from every environment template - one less thing to wonder about in a security review.
-
Webhook setup follows your permissions
If your organisation's webhook allowlist is empty, the rule editor now says so up front instead of letting you fill in a destination that could never be saved.
-
Full Content Security Policy, measured first
A complete Content Security Policy with per-request script nonces shipped in report-only mode - real-browser telemetry before enforcement, so the lockdown cannot break the console.
-
The save button knows when there is nothing to save
The webhook allowlist's save action stays disabled until the list actually differs from what is stored.
-
A real provider console
The platform console grew from a single form into a tenant overview: every customer's plan, status, usage against limits and expiry at a glance, with plan management one click away.
-
Slack destinations pinned to Slack
Slack notification URLs must now point at Slack's own webhook host - a mistyped or malicious destination is refused at save time.
-
Webhook destinations under tenant-admin control
A per-organisation allowlist now governs where webhook notifications may be sent. Administrators approve hosts; nobody else can point dead-letter data - which may contain personal information - at an unapproved destination. Closed by default.
-
Webhook secrets: generated, shown once, never returned
Signing secrets can be generated with one click, are displayed exactly once, and never travel back to a browser again. Saving without touching the secret keeps the stored one; testing always signs with what is actually stored.
-
A signed webhook channel for everything else
Alongside Slack, Teams and Splunk, notifications can now go to any HTTPS endpoint you run - as structured JSON, HMAC-signed with a timestamped signature scheme and stable delivery ids for safe deduplication, with private-network destinations refused outright.
-
Strict transport security on every endpoint
The API now emits HTTP Strict Transport Security behind the load balancer as well - browsers pin every OpsChisel connection to HTTPS for a full year, on both the console and the API.
-
Hardened response headers across both hosts
One-year HSTS with preload in every environment, and the web server fingerprint removed from all responses - two fewer things for a security review to flag.
-
Published performance receipts and a product FAQ
The stress-test program's measured results - throughput, cost per message, loss record - are now documented alongside a plain-language FAQ, so evaluations can start from numbers instead of claims.
-
The send button tells the truth, live
The moment a dead-letter is resent anywhere, the send button greys out in every other open window with who resent it and when. Choosing a different destination re-enables it - deliberate second deliveries stay one click away, accidental ones become impossible.
-
Duplicate-delivery protection on resend
Resending a message that was already resent is now refused with a clear reason instead of silently delivering a duplicate - even from a window opened before the first resend. Messages that fail again return to the queue and remain resendable; the legitimate retry loop is untouched.
-
Real-time backplane and admin roster as infrastructure code
The provider-admin roster and the real-time messaging backplane are provisioned by the deployment template itself, so environment configuration can never silently drift or disappear across releases.
-
Bulk removals count down live
Large entity removals now report progress every few seconds - "1,445 left... 927... 407..." - identically in every open window, instead of showing a frozen number until everything is done.
-
Clearer bulk-deletion diagnostics
Deletion telemetry now states precisely what the storage service acknowledged versus what is still draining in the background - operational dashboards stop over-reporting completion.
-
Totals are honest the moment a removal finishes
When an entity's removal completes, namespace totals drop by exactly its message count immediately - no more minute-long window where deleted messages still appeared in the numbers.
-
No dead-end resends on deleted entities
Entities that no longer exist in Service Bus show resend as unavailable with an explanation, and destination pickers never offer them. Sending the messages somewhere else, archiving and deleting all remain available.
-
Removal state shared across every window
Starting an entity removal now marks it for every operator and every session - spinner, live progress and a disabled remove action everywhere, including windows opened mid-removal - with a safe restart if a removal ever looks stuck.
-
Concurrent removals can no longer collide
Two operators (or two windows) triggering the same entity removal now both complete cleanly - the second simply confirms the work is done instead of erroring.
-
Cost-management rehearsal for spike cleanups
The load-lab protocol now rehearses the full spike-purge cycle - scale database throughput up for a fast purge, back down afterwards, and merge storage partitions - before production ever needs it.
-
Server-side bulk deletion (preview)
Emptying an entire entity now uses a single server-side partition delete instead of thousands of per-message operations. Measured: deleting 21,000 messages consumed ~55 request units of interactive budget - roughly 4,000x less than the paged path - with the actual deletion draining in the background at zero cost to foreground users.
-
Sessions survive upgrades silently
Sign-in tokens are now cached durably across service upgrades - operators stop being asked to sign in again after a release rolls out mid-shift.
-
Load-lab stand-up runbook
Step-by-step stand-up documentation for the disposable, production-shaped load environment.
-
One-command load-lab identity provisioning
The deployment-identity script now provisions the disposable load environment end to end.
-
Point-in-time backup, decided at creation
Continuous backup (7- or 30-day point-in-time restore) is now a first-class deployment decision, made when an environment's database account is created - because it cannot be added later.
-
Documented load-test click protocol
The measured UX click protocol, baselines and teardown checklist for load sessions are now in the repository.
-
Stress-test findings published (runs up to 10)
The serverless stress program's results are documented, including the discovery and elimination of a single query that consumed 97% of the daily database budget.
-
Bulk deletes show live progress
Counts tick down while a bulk delete runs, so a healthy operation never looks hung.
-
Background maintenance cost cut ~1,500x
The recurring statistics sweep now reads compact counter documents instead of scanning message documents - from ~1.4 million request units per day to under a thousand, independent of how many messages are stored.
-
Overview queries ~934x cheaper
Namespace overviews read maintained per-entity counters instead of live-counting message documents. Display cost now scales with the number of entities, not the number of stored messages - flat whether you hold ten thousand messages or ten million.
-
Deletes stopped paying a storage tax
Bulk deletion no longer makes a cloud-storage call per message (18,000 calls for an 18,000-message sweep, nearly all unnecessary) - only the rare oversized payloads that actually spilled to blob storage are cleaned up there.
-
Calmer under pressure, fresher when idle
Throttling now produces at most one quiet notification per episode instead of a storm, and idle overview pages re-query on their own so banked dead-letters appear without a refresh.
-
Pages paint instantly
The namespace page renders its frame immediately and loads data after - opening it during peak load went from up to 15 seconds to a few milliseconds, measured under saturation.
-
Notification bell polish
The in-app notification history opens reliably across component-library upgrades.
-
Deployment gate accuracy
The self-verifying deployment gate no longer reports a healthy release as failed due to output parsing.
-
Database platform compatibility
Deployment templates track the resource-provider API version required for priority-based execution.
-
Notification bell opens reliably
First iteration of the bell-panel fix.
-
Elastic scale, parameterized
API replica range and worker instance counts are deployment parameters, with a complete definition for a disposable production-shaped load environment.
-
Production database shape
Provisioned throughput layout for production: a shared pool for control-plane data and dedicated, independently scaling budgets for messages and audit - so a message-ingest storm can never starve the control plane.
-
Interactive users win under load
On provisioned database accounts, bulk writes are tagged low priority so operator reads and clicks take precedence when throughput is contended.
-
Stress-test findings published (runs 4-9)
Payload cost calibration, the circuit breaker under deliberate fire, and the before/after of saturation UX improvements.
-
Deployments verify themselves
A release is only reported green after the platform confirms the new version is actually serving traffic and its health endpoints answer - eliminating the silently-failed deploy.
-
A notification bell with memory
Every toast from the session is kept in an Azure-portal-style bell with timestamps and unread state - a transient error message is never lost to a click again.
-
Windows can no longer freeze mid-drain
Saturated reads are detected and retried gracefully; live views always recover on their own.
-
Consistent counts across replicas and releases
Service Bus count snapshots are shared storage-side, so scaling out or rolling a release never shows different numbers in different windows or resets counts to zero.
-
Oversized-payload hardening
Multi-megabyte messages spill to blob storage transparently, with a bounded search projection and a complete cleanup lifecycle - one oversized message can never poison capture for anyone else.
-
Graceful degradation under throttling
When the database is saturated, dashboards degrade quietly with honest retry hints instead of red error storms - while state-changing actions remain loudly explicit about failures.
-
Live views survive releases
Real-time subscriptions replay automatically after a reconnect, so an API deployment mid-incident no longer silences anyone's live view.
-
Settings saves never lose a race
Concurrent configuration changes (rapid toggles, background sync) merge safely with optimistic concurrency instead of overwriting each other.
-
Circuit-breaker hardening
The capture pump's storage-outage breaker survived deliberate saturation testing; a deadlock found under fire was eliminated the same night.
-
Ghost alerts eliminated
Fully removed entities can no longer keep firing stale backlog alerts - counters reconcile and clean themselves up.
-
Long operations without timeouts
Bulk sweeps hand off to a background queue and reschedule themselves instead of holding a web request - a 60-second operation can no longer error at the finish line. (Shipped across three changes, 50-52.)
-
Capture pauses safely during storage outages
A sustained storage outage now pauses dead-letter capture cleanly - messages wait unacknowledged in Service Bus, nothing is dropped - and capture resumes automatically when storage recovers.
-
Precise, component-selectable deployments
Deploy the API, console or worker independently, with readiness probes gating traffic switchover - groundwork for zero-downtime releases.
-
Payload editor catches duplicate keys
The JSON editor flags duplicate property names - a class of silent payload corruption - before send.
-
Guided cleanup for deleted entities
Entities deleted from Service Bus get a clear marker and a guided remove-everything flow that deletes captured and archived messages and then removes the entity - with an explicit, spelled-out confirmation.
-
Multi-namespace correctness hardening
Capture workers are fully namespace-qualified, closing a correctness gap when identically-named entities exist across namespaces.
See it on your own dead-letters.
Everything above is live in the product today. Connect a namespace with Entra RBAC and DLQ Manager starts capturing in minutes - free for 30 days.