# Migrating from ActiveMQ (/connectors/how-to/migration/from-activemq)



ActiveMQ is a multi-protocol broker, so there is no single migration path. Which connector you
use — and which guide you follow — depends on **which protocol your client speaks** and which
ActiveMQ variant (Classic or Artemis) you run. This page is the router: it points you at the
right per-protocol guide and calls out the one thing that does **not** migrate at all.

KubeMQ serves ActiveMQ workloads through three existing connectors — **AMQP 1.0**, **STOMP**, and
**MQTT** — depending on the protocol. All three are **opt-in** (`Enable = false` by default); you
enable only the connector(s) your clients need. The per-protocol guides carry the full code; this
page keeps the endpoint deltas and the cross-cutting deviations in one place.

<Callout type="warn">
  **OpenWire is NOT supported.** KubeMQ has no OpenWire wire decoder. Any client connecting over
  the OpenWire protocol will fail. There is no configuration option to add OpenWire support — an
  ActiveMQ client using the default OpenWire transport must switch to AMQP 1.0, STOMP, or MQTT
  before it can talk to KubeMQ.
</Callout>

## Choose your path [#choose-your-path]

Pick the row that matches your client, then follow the linked guide for the connection snippet,
destination mapping, and a working code example.

| Client type                  | ActiveMQ variant          | Connector                      | Guide                                                                    |
| ---------------------------- | ------------------------- | ------------------------------ | ------------------------------------------------------------------------ |
| Java / JMS applications      | Classic or Artemis        | AMQP 1.0 (via Apache Qpid JMS) | [Migrating from JMS](/connectors/how-to/migration/from-jms)              |
| Non-Java clients using STOMP | Classic or Artemis        | STOMP                          | [Migrating from STOMP](/connectors/stomp/scenarios/migration-from-stomp) |
| Non-Java clients using MQTT  | Classic or Artemis        | MQTT                           | [Migrating from MQTT](/connectors/mqtt/scenarios/migration)              |
| Native AMQP 1.0 clients      | Artemis (native AMQP 1.0) | AMQP 1.0                       | [Migrating from AMQP 1.0](/connectors/how-to/migration/from-amqp-1-0)    |

Java/JMS applications keep their JMS code and swap only the `ConnectionFactory` implementation to
Apache Qpid JMS — a **client-swap**. STOMP, MQTT, and native AMQP 1.0 clients are **endpoint-only**:
change the broker host and credentials, nothing else.

Default ports (when the connector is enabled):

| Connector | Port  | TLS port       | Protocol                     |
| --------- | ----- | -------------- | ---------------------------- |
| AMQP 1.0  | 5672  | 5671           | AMQP 1.0 (Qpid JMS, Artemis) |
| STOMP     | 61613 | 61614          | STOMP 1.0 / 1.1 / 1.2        |
| MQTT      | 1883  | 8883 (WS 8083) | MQTT 3.1.1 / 5.0             |

Enable only what you need. Each connector has its own enable variable:

```bash title="Enable variables"
CONNECTORS_AMQP10_ENABLE=true   # Java/JMS via Qpid JMS, and native AMQP 1.0 (Artemis) clients
CONNECTORS_STOMP_ENABLE=true    # STOMP clients (Classic and Artemis)
CONNECTORSMQTT_ENABLE=true      # MQTT clients (note: no underscore)
```

## Compatibility Matrix [#compatibility-matrix]

This matrix is self-contained for the ActiveMQ workload across all three connectors. Where a
capability differs by path, the cell names the path it applies to.

| Dimension             | Status                   | Notes                                                                                                 |
| --------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- |
| Drop-in level         | client-swap / endpoint   | Java/JMS: client-swap (Qpid JMS); STOMP/MQTT: endpoint-only                                           |
| Point-to-point queues | ✅                        | All three connectors support Queues                                                                   |
| Pub/sub (non-durable) | ✅                        | Events pattern on all paths                                                                           |
| Durable subscriptions | ✅                        | Via Events Store; `unsubscribe()` is node-local — see [Behavioral deviations](#behavioral-deviations) |
| Request/reply (RPC)   | ✅ ²                      | AMQP 1.0 (Qpid JMS) path only                                                                         |
| Ordering              | ⚠️ node-local            | Per-channel ordering is not preserved cluster-wide                                                    |
| Transactions          | ❌                        | Not supported on any path                                                                             |
| Dead-letter / redrive | ❌ no client DLQ ⁶        | No client-settable DLQ; poison messages are silently dropped                                          |
| Selectors / filtering | ✅ (AMQP 1.0) / ❌ (STOMP) | SQL92 selectors work on the AMQP 1.0 path (Events / Events Store); no selectors on STOMP              |
| Auth model            | PLAIN (JWT)              | JWT in SASL PLAIN password (AMQP 1.0), CONNECT passcode (STOMP), or CONNECT password (MQTT)           |
| TLS / mTLS            | ✅                        | 5671 (AMQP 1.0), 61614 (STOMP), 8883 / wss 8083 (MQTT)                                                |
| Top unsupported       | —                        | **OpenWire protocol**; transactions; selectors on the STOMP path                                      |

**Footnotes:**

* ² ActiveMQ RPC via the AMQP 1.0 (Qpid JMS) path only; STOMP reply-to works but requires a
  pre-existing reply subscription.
* ⁶ See [What Does NOT Migrate → Hard blockers](#hard-blockers) for the authoritative statement.

## Connection / Endpoint Migration [#connection--endpoint-migration]

The change is the same shape on every path: point the client at the KubeMQ host and supply a
KubeMQ JWT as the credential. The full code lives in the linked per-protocol guides — these tabs
show only the endpoint delta.

<Tabs groupId="protocol" items="['AMQP 1.0', 'STOMP', 'MQTT']">
  <Tab value="AMQP 1.0">
    Java applications using the ActiveMQ JMS client (`ActiveMQConnectionFactory`) migrate by swapping
    the `ConnectionFactory` implementation to Apache Qpid JMS — the JMS application code itself does
    not change. Native AMQP 1.0 clients (e.g. `go-amqp`, AMQP.NET Lite, Qpid Proton) and Artemis
    clients that already speak AMQP 1.0 migrate by changing only the broker endpoint.

    ```text title="ConnectionFactory / broker URI"
    # Before (ActiveMQ Classic, OpenWire — must switch protocol)
    tcp://activemq.example.com:61616

    # Before (ActiveMQ Artemis, native AMQP 1.0)
    amqp://artemis.example.com:5672

    # After (KubeMQ)
    amqp://kubemq.example.com:5672
    amqps://kubemq.example.com:5671   # TLS
    ```

    For the JNDI setup, destination mapping, and the full Qpid JMS snippet, see
    [Migrating from JMS](/connectors/how-to/migration/from-jms). For the native AMQP 1.0 path
    (addressing, message translation, RPC, and the `go-amqp` snippet), see
    [Migrating from AMQP 1.0](/connectors/how-to/migration/from-amqp-1-0).
  </Tab>

  <Tab value="STOMP">
    ```text title="STOMP endpoint"
    # Before (ActiveMQ Classic STOMP)
    host: activemq.example.com
    port: 61613

    # After (KubeMQ STOMP)
    host: kubemq.example.com
    port: 61613   # same port; TLS on 61614
    ```

    **Destination compatibility note:** ActiveMQ uses `/queue/NAME` and `/topic/NAME` with
    `.`-delimited names. KubeMQ accepts both forms — `/topic/orders.created` and
    `/topic/orders/created` reach the same KubeMQ channel `orders.created`. Pick one convention and
    apply it consistently.

    For destinations, ack modes, durable subscriptions, and the full `stomp.py` snippet, see
    [Migrating from STOMP](/connectors/stomp/scenarios/migration-from-stomp).
  </Tab>

  <Tab value="MQTT">
    ```text title="MQTT endpoint"
    # Before (ActiveMQ Classic MQTT)
    host: activemq.example.com
    port: 1883

    # After (KubeMQ MQTT)
    host: kubemq.example.com
    port: 1883   # plain; TLS on 8883; WS on 8083
    ```

    **MQTT version note:** KubeMQ **rejects MQTT 3.1 clients** at CONNECT. Use MQTT 3.1.1 (the
    default for most clients, including Eclipse Paho) or MQTT 5.0.

    For topic→pattern mapping, QoS, and the `paho-mqtt` snippet, see
    [Migrating from MQTT](/connectors/mqtt/scenarios/migration).
  </Tab>
</Tabs>

## Concept & Destination Mapping [#concept--destination-mapping]

ActiveMQ concepts map onto KubeMQ patterns through the connector chosen for each client type.

### AMQP 1.0 path (Qpid JMS / Artemis) [#amqp-10-path-qpid-jms--artemis]

| ActiveMQ concept           | KubeMQ pattern                           | Channel / address                      |
| -------------------------- | ---------------------------------------- | -------------------------------------- |
| Queue                      | Queues                                   | `/queues/<name>`                       |
| Topic (non-durable)        | Events                                   | `/events/<name>`                       |
| Durable topic subscription | Events Store                             | `/events-store/<name>`                 |
| Temporary queue            | Dynamic node (temp reply mailbox)        | `source.dynamic = true`                |
| Virtual Topic / shared sub | Consumer group                           | link property `x-opt-kubemq-group`     |
| Command (request/reply)    | Commands or Queries                      | `/commands/<name>` / `/queries/<name>` |
| Reply-to                   | `/responses/<RequestID>` or dynamic node | —                                      |

The JMS capability hint (`queue` / `topic`) lets Qpid JMS `Queue("orders")` and `Topic("orders")`
map automatically without an explicit prefix — see
[Migrating from JMS](/connectors/how-to/migration/from-jms) for details.

### STOMP path [#stomp-path]

| ActiveMQ destination                    | KubeMQ destination      | Pattern      |
| --------------------------------------- | ----------------------- | ------------ |
| `/queue/NAME`                           | `/queue/NAME`           | Queues       |
| `/topic/NAME`                           | `/topic/NAME`           | Events       |
| Durable topic                           | `/topic-store/NAME`     | Events Store |
| ActiveMQ Virtual Topic `VirtualTopic.X` | `/topic/VirtualTopic.X` | Events       |

### MQTT path [#mqtt-path]

| ActiveMQ MQTT topic prefix | KubeMQ pattern           |
| -------------------------- | ------------------------ |
| `events/<channel>`         | Events                   |
| `store/<channel>`          | Events Store             |
| `queues/<channel>`         | Queues                   |
| `commands/<channel>`       | Commands (MQTT 5.0 only) |
| `queries/<channel>`        | Queries (MQTT 5.0 only)  |

Wildcards `+` and `#` are supported **for Events subscriptions only**.

## Security [#security]

All three connectors accept the same KubeMQ JWT as the credential, but deliver it differently:

| Connector | Where the JWT goes                                               | Auth disabled                          |
| --------- | ---------------------------------------------------------------- | -------------------------------------- |
| AMQP 1.0  | SASL PLAIN **password** field (username is informational)        | ANONYMOUS or bare AMQP header accepted |
| STOMP     | CONNECT &#x2A;*`passcode`** header (username recorded for audit) | Any credentials accepted               |
| MQTT      | CONNECT &#x2A;*`password`** field (username recorded for audit)  | Any credentials accepted               |

All three connectors are **opt-in** (`Enable = false`). They do not open listeners until
explicitly enabled. When `Authentication.Enable = false` (the server default), listeners accept
unauthenticated clients — enable authentication or firewall the ports when the server is reachable
from untrusted networks.

**TLS:** each connector uses the server-wide `Security` block. TLS is active on the TLS port only
when `Security` is configured. mTLS (client-certificate auth) is available on the AMQP 1.0 path
via SASL EXTERNAL (cert CN = ClientID).

**Authorization (Casbin):** with `Authorization.Enable = true`, Write is enforced on SEND /
produce, and Read on SUBSCRIBE / consume, against the resolved KubeMQ channel.

See [Authentication & Security](/connectors/reference/auth-and-security) and the
[configuration reference](/configure/reference/connectors).

## What Does NOT Migrate / Deviations [#what-does-not-migrate--deviations]

### Hard blockers [#hard-blockers]

| Feature                            | Status          | Detail                                                                                                                                                                                                             |
| ---------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **OpenWire protocol**              | ❌ Not supported | See the callout at the top of this page. There is no configuration option to add OpenWire support.                                                                                                                 |
| **Transactions**                   | ❌ Not supported | No `SESSION_TRANSACTED` / XA (JMS), no STOMP `BEGIN` / `COMMIT` / `ABORT`. Use idempotent producers and at-least-once consumers instead.                                                                           |
| **Message selectors (STOMP path)** | ❌ Not supported | The STOMP connector rejects `selector` headers with ERROR `selectors not supported` and closes the connection. Remove all `selector` usage from STOMP applications.                                                |
| **No client-settable DLQ**         | ❌               | No dead-letter address is exposed to clients over AMQP 1.0, STOMP, or MQTT. A message that exceeds `MaxReceiveCount` is silently dropped — there is no consumable dead-letter address over any of these protocols. |

### Behavioral deviations [#behavioral-deviations]

| Feature                            | Deviation                                                                                                                                                                                                                                                                        |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Selectors (AMQP 1.0 path)**      | Supported on Events / Events Store only (SQL92 subset via `apache.org:selector-filter`). Rejected on `/queues/` links (`amqp:not-implemented`).                                                                                                                                  |
| **ActiveMQ durable subscriptions** | Map to Events Store via `/events-store/<name>` (AMQP 1.0) or `/topic-store/<name>` (STOMP). Replay-position headers control where the subscription starts. `unsubscribe()` / DETACH of the durable identity is **node-local** — connect back to the same node to cleanly detach. |
| **ActiveMQ Virtual Topics**        | Map to KubeMQ consumer groups via link property `x-opt-kubemq-group` (AMQP 1.0) or a shared STOMP subscription. No automatic `VirtualTopic.` prefix translation.                                                                                                                 |
| **Ordering**                       | Per-channel ordering is node-local, not cluster-wide. MQTT ordering is QoS-dependent (QoS 0 unordered; QoS 1/2 ordered per connection only).                                                                                                                                     |
| **STOMP reply-to RPC**             | The reply subscription must be active before the SEND carrying `reply-to` is issued. Sending without a pre-existing reply subscription produces ERROR `reply-to subscription required` and closes the connection.                                                                |
| **MQTT 3.1 rejected**              | KubeMQ refuses MQTT 3.1 clients at CONNECT. Use MQTT 3.1.1 or 5.0.                                                                                                                                                                                                               |
| **MQTT retained messages**         | `RetainAvailable = 0`. Retained publishes are rejected with an audit event (not silently dropped).                                                                                                                                                                               |
| **MQTT RPC**                       | Request/reply (Commands / Queries) requires MQTT 5.0. Not available over MQTT 3.1.1.                                                                                                                                                                                             |

## Verification Smoke Test [#verification-smoke-test]

Choose the path that matches your application, enable the relevant connector(s), and point a test
client at the KubeMQ endpoint. The AMQP 1.0 and MQTT paths defer to their guides for the full
client snippet; the STOMP quick check is below.

* **AMQP 1.0 path (Java/JMS)** — requires the AMQP 1.0 connector enabled
  (`CONNECTORS_AMQP10_ENABLE=true`). See [Migrating from JMS](/connectors/how-to/migration/from-jms)
  for the full Qpid JMS snippet, and [Migrating from AMQP 1.0](/connectors/how-to/migration/from-amqp-1-0)
  for the native `go-amqp` snippet.
* **MQTT path** — requires the MQTT connector enabled (`CONNECTORSMQTT_ENABLE=true`). See
  [Migrating from MQTT](/connectors/mqtt/scenarios/migration) for the full `paho-mqtt` snippet.

**STOMP path** — requires the STOMP connector enabled (`CONNECTORS_STOMP_ENABLE=true`):

```python title="smoke_test.py"
# stomp.py 8.x — publish one message, consume it, confirm arrival
# Symbols: stomp.Connection, conn.connect, conn.send, conn.subscribe,
#          ConnectionListener.on_message, conn.ack, conn.disconnect

import stomp, time

class Listener(stomp.ConnectionListener):
    def __init__(self): self.received = []
    def on_message(self, frame):
        self.received.append(frame.body)
        print(f"received: {frame.body}")

listener = Listener()
conn = stomp.Connection([("kubemq.example.com", 61613)])
conn.set_listener("", listener)
conn.connect(login="user", passcode="<jwt-or-empty>", wait=True)

# Subscribe before publishing (required for Events pattern)
conn.subscribe("/topic/smoke-test", id=1, ack="auto")

# Publish
conn.send("/topic/smoke-test", body="hello from activemq migration")
time.sleep(1)

assert len(listener.received) == 1, "smoke test failed: no message received"
print("smoke test passed")
conn.disconnect()
```

## See Also [#see-also]

<Cards>
  <Card title="Migration hub" href="/connectors/how-to/migration" description="The connector map, the cross-protocol comparison matrix, and every ecosystem guide." />

  <Card title="Migrating from JMS" href="/connectors/how-to/migration/from-jms" description="The primary Java/ActiveMQ path — swap the ConnectionFactory to Apache Qpid JMS over AMQP 1.0." />

  <Card title="Migrating from AMQP 1.0" href="/connectors/how-to/migration/from-amqp-1-0" description="Native AMQP 1.0 (Artemis) clients — address-prefix mapping, a go-amqp example, and RPC." />

  <Card title="Migrating from STOMP" href="/connectors/stomp/scenarios/migration-from-stomp" description="STOMP client migration — every destination type maps; the stomp.py snippet and ack modes." />

  <Card title="Migrating from MQTT" href="/connectors/mqtt/scenarios/migration" description="MQTT client migration — topic-prefix mapping, QoS, retain/RPC caveats, and 3.1.1/5.0 support." />

  <Card title="AMQP 1.0 connector reference" href="/connectors/amqp/reference/capabilities" description="Wire contract and known deviations for the AMQP 1.0 connector." />

  <Card title="STOMP connector reference" href="/connectors/stomp/reference/capabilities" description="Wire contract, error frames, and ack modes for the STOMP connector." />

  <Card title="MQTT connector reference" href="/connectors/mqtt/reference/capabilities" description="Topic mapping, QoS, and session behavior for the MQTT connector." />

  <Card title="Connector configuration reference" href="/configure/reference/connectors" description="Configuration fields and enable variables for all connectors." />
</Cards>
