---
title: "Conformance"
description: "The other half of the evidence: every client suite run against every applicable topology in its own throwaway stack, the tenancy parity gate, and the two-tenant isolation run."
---

> Queen MQ documentation, for AI agents
> Complete self-contained summary of Queen MQ: https://queenmq.com/llms-brief.txt
> Fetch that first when the question is about the product rather than about this page.
> Index of all pages: https://queenmq.com/llms.txt

# Conformance

The throughput pages measure how fast one shape goes. This page is the other half of the
evidence: whether the clients and the broker agree about what the API means, on more than one
topology, every time.

One command is the whole thing.

```bash
test/run.sh
```

It builds a broker image from the current tree, builds one runner image per suite, then runs
every applicable pair of suite and topology as its own `docker compose` project on its own
private network, in parallel, and prints a pass/fail matrix. Nothing binds a host port and every
PostgreSQL runs on `tmpfs`, so a run cannot collide with another run or with a database you are
using.

## What runs

Seven client suites cover six SDK languages and the CLI, and each of the seven runs on three
topologies. Five more suites bring their own.

| Suite | What it exercises | Topologies |
| --- | --- | --- |
| `js` | `clients/client-js/test-v2`: the broker-free unit tests including the proxy `429` contract, then the integration run | `single`, `ha`, `tenanted` |
| `go` | the root-package unit tests, then `./tests/` and `./tests/streams_integration/` with `-count=1`, so a cached result never hides a live-broker failure | `single`, `ha`, `tenanted` |
| `py` | the whole `pytest` tree under `clients/client-py/tests`, streams included | `single`, `ha`, `tenanted` |
| `cli` | the `queenctl` end-to-end suite, with `QUEEN_E2E=1` and the PostgreSQL variables that turn on its database-side assertions | `single`, `ha`, `tenanted` |
| `cpp` | the broker-free binaries first, `test_retry429`, `test_kv_timers` and `test_conflation`, then `test_client` against the broker | `single`, `ha`, `tenanted` |
| `laravel` | the PHP client's `phpunit` run: the broker-free `Unit` suite that pins the exact JSON wire shape, then the `Integration` tree | `single`, `ha`, `tenanted` |
| `rust-client` | `cargo test --locked` in `clients/client-rust`: the lib unit tests, then each integration binary in turn | `single`, `ha`, `tenanted` |
| `rust` | the **broker's** own in-process unit tests, `cargo test`, no stack and no PostgreSQL | `unit` |
| `mesh` | that both brokers of an HA pair report the peer connected with 0 handshake failures | `ha` |
| `tenancy` | two-tenant isolation over the HA pair, driven at the brokers with the trusted `x-queen-tenant` header | `ha-tenanted` |
| `http` | the kv/timer wire with no SDK in the way: a broker-free unit half, then the route-by-route check against the broker | `single` |
| `conflation` | the conflation end-to-end scenarios, raw HTTP with no SDK in the path | `single` |

The `rust` row is the broker, not the Rust client: the client suite is `rust-client`. The two are
separate rows because they prove separate things, and only one of them needs a database.

Two entrypoint details are the difference between running and passing vacuously. The
`rust-client` runner exports `QUEEN_TEST_URL` (without it every integration test skips) and
`QUEEN_TEST_STRICT=1`, which makes the skip branch itself fatal, so an empty broker URL fails
instead of reading like a green run of a few hundred tests. The `cli` runner exports `QUEEN_E2E=1`,
without which `TestMain` exits 0 having run nothing.

## The topologies

| Topology | Stack | `QUEEN_TENANCY_HEADER` |
| --- | --- | --- |
| `single` | one PostgreSQL, one broker | off |
| `ha` | one PostgreSQL, `queen-a` and `queen-b` as a framed-TCP mesh pair, client suites hitting `queen-a` | off |
| `tenanted` | the `single` stack, with the broker started with native tenant scoping on while the suite sends **no** tenant header | on |
| `ha-tenanted` | the `ha` pair with the flag on, the substrate for the `tenancy` suite | on |

Running the client suites on `ha` is what makes [high availability](/deploy/ha) a tested claim
rather than a topology diagram: the same unmodified suite, pointed at one broker of a mesh pair
sharing one PostgreSQL, has to produce the same result it produces against a single broker.

## The tenancy parity gate

The `tenanted` lane exists to prove a negative. Turning native tenant scoping on must change
nothing for a client that sends no tenant header, which is the default-tenant path every
[multi-tenant cell](/deploy/multi-tenant) serves. So `run.sh` runs the unmodified suite on both
lanes and prints a `TENANCY PARITY` verdict.

The exit code is the hard gate. Because an exit code is coarse (99 of 112 and 100 of 112 are both
`rc=1`), `run.sh` also parses each suite's printed pass tally where one exists, counts only and
never durations, and compares that too. **A divergence fails the run in either direction.** A
behaviour change caused by the flag is a regression even when the flag-on side is the greener one.

The two lanes share their compose file, with `run.sh` exporting `QUEEN_TEST_TENANCY`. Duplicating
the stack definitions would let them drift, which is exactly what the gate exists to catch.

## The isolation run

`test/runners/tenancy/tenancy-check.sh` drives the HA pair directly. Every scenario deliberately
uses the *same* queue name, the *same* partition name and the *same* consumer-group name for both
tenants, with traffic on both brokers, so shared-name collisions are the default rather than the
exception. Eight scenarios:

| # | What it asserts |
| --- | --- |
| 1 | queue identity and configuration are per-tenant, read back consistently on both brokers after each tenant configured on a different one |
| 2 | no message crosses tenants: push on one broker, pop on the other |
| 3 | a foreign `partitionId` cannot advance another tenant's cursor |
| 4 | deduplication keys are per-tenant, while within-tenant deduplication still fires |
| 5 | listings are scoped |
| 6 | a consumer-group *name* shared by two tenants keeps independent cursors |
| 7 | one tenant's claim-and-ack cannot hide or delay the other's pending message through the in-process hot-list ring |
| 8 | a push by one tenant delivers nothing to another tenant's parked long poll |

The run recorded on 2026-07-29 against a freshly built image is **45 assertions, 0 failures**,
5 notes, in 21 seconds.

**It refuses to pass vacuously.** A probe up front configures one queue name for two tenants with
different lease times and aborts if the broker does not keep them apart, so the lane can never
pass by comparing the default tenant with itself. Expected and harmless crosstalk is printed as
`note` lines rather than asserted: PostgreSQL is the authority on those paths and every
stored-procedure call carries the tenant, so the cost is a re-query, not a leak.

## What this evidence does not cover

- **A green cell is a screen, not a proof.** `--exit-code-from runner` with
  `--abort-on-container-exit` can yield 0 for a runner that was merely stopped, and `run.sh`
  scores 0 as `PASS`. Each cell prints its duration next to `PASS` so an anomalously short run
  stands out, and the per-cell logs are the evidence.
- **Streaming window arithmetic is the noisy part.** The failing set moves between runs and
  between lanes, and this site therefore makes no per-test verification claim about window
  arithmetic.
- **Two failures are known and deterministic**: `TestGateTokenBucketBasic` in the Go client, and
  `TestLoad_BenchSmoke` in the CLI, which is a benchmark deadline rather than a semantic check.
- **The `mesh` suite asserts connection, not behaviour.** Cross-replica wake latency, dead-peer
  detection and reconnection are `server/mesh-verify.sh`, run by hand.
- **The proxy is not in this matrix.** `queen_proxy`'s own unit tests run with `cargo test`
  inside `proxy/`, and its two-tenant end-to-end check is `proxy/scripts/isolation-smoke.sh`.

The full harness, including how to run a subset and what each runner maps its environment
variables onto, is in [Testing](/internals/contributing/testing/). The performance rigs and the
archive are in [method, rig and archive](/benchmarks/method/).

Source: https://queenmq.com/benchmarks/conformance/index.mdx
