RocketMQ
pg addon install rocketmq runs Apache RocketMQ 5.x as a managed addon from the official docker.io/apache/rocketmq image. Like Kafka, ClickHouse and RabbitMQ it is a top-level addon that does not front a PostgreSQL instance.
Each instance is three containers on the host network: a NameServer, a broker and a proxy. The same shape is used in both modes, so ports, commands, logs and lifecycle behave identically:
- Standalone — one NameServer with no controller, one async master broker with no replicas, and a proxy. This is the quickest way to send and receive messages. The 4.x master/slave and DLedger broker deployment modes are not used.
- Multi-host cluster — every NameServer embeds a DLedger (Raft) controller, the brokers run in controller mode, and one broker is elected master while another takes over automatically when it fails. The proxy is the client entry point. This is RocketMQ 5.x’s auto-failover deployment mode.
There is no authentication and no TLS. RocketMQ listens on host networking, and cluster ports are fixed. Anyone who can reach the NameServer, broker or proxy ports can read and write every topic. Run it only on a trusted private network or behind a firewall that restricts
9876,9877,10911,10912,8080and8081. There is also no web UI and no ACL in this addon.
Parameters
| Flag | Default | Description |
|---|---|---|
--name |
rocketmq |
Instance name (map key; also the default subcommand name) |
--version |
5.5.0 |
Upstream image tag, pulled as docker.io/apache/rocketmq:<version>. Only 5.x releases are accepted |
--data-dir |
<base_dir>/addon/rocketmq/<name>/data |
Instance data root: the broker store is <dir>/broker and, in cluster mode, the controller store is <dir>/controller. Must be absolute except for base_dir-relative paths |
--advertise-host |
127.0.0.1 standalone; required cluster |
Host advertised to clients and peers. Cluster mode requires a concrete non-loopback IPv4 address; hostnames, IPv6 and 0.0.0.0 are rejected. Set it to the host’s LAN IP for standalone instances that remote clients use |
--cluster NAME |
— | Switch on multi-host cluster mode. Every host must use the same name; it becomes the DLedger controller group and the broker cluster/group name. Cluster identity is immutable after install |
--controller-id ID |
— | This node’s controller member id (n0, n1, …). Required on a fresh cluster install; must be unique in the group and match [A-Za-z][A-Za-z0-9]{0,31}. Rejected in standalone mode |
--peer ID@HOST |
— | Another controller member. Repeat once per other node, with a bare non-loopback IPv4 host and no port (the controller port is fixed at 9877). Pass the full list of the other members on every host; the local peer is added automatically. Rejected in standalone mode |
--namesrv-port |
auto (9876) standalone |
NameServer host port. 0 = auto-assign from the RocketMQ pool. Standalone only; cluster members are fixed at 9876 |
--broker-port |
auto (10911) standalone |
Broker listen port; HA is broker_port + 1 and the VIP port is broker_port - 2. Standalone only; cluster members are fixed at 10911 |
--proxy-port |
auto (8080) standalone |
Proxy remoting port. Standalone only; cluster members are fixed at 8080 |
--grpc-port |
auto (8081) standalone |
Proxy gRPC port for 5.x SDKs. Standalone only; cluster members are fixed at 8081 |
--controller-port |
— | Embedded controller port. Not accepted in standalone mode; cluster members are fixed at 9877 |
--heap |
512m |
Broker JVM heap, applied as JAVA_OPT_EXT=-Xms<size> -Xmx<size> |
--namesrv-heap |
256m |
NameServer JVM heap |
--proxy-heap |
256m |
Proxy JVM heap |
--config-option K=V |
— | Extra broker.conf setting (flushDiskType=SYNC_FLUSH, brokerPermission=4); repeatable and replaces the stored override list. pgcli-managed keys are rejected (identity, listeners, store paths, controller settings, replication settings, autoCreateTopicEnable) |
--force |
false | Re-render the three configs and recreate the three containers, keeping the broker store and controller store. Cluster identity and fixed ports cannot be changed even with --force |
--image, --listen, --tls, --tls-pem, --tls-cert, --tls-key, --node-id, --cluster-id and --join do not apply to RocketMQ and are rejected. Use --version to select the image.
Install a standalone instance
The install pulls the image if needed, renders the configs, creates the directories, starts namesrv → broker → proxy, and waits for the NameServer, broker registration and both proxy listeners:
To let clients on other hosts connect, advertise the host’s LAN address (the proxy config and broker both use it):
A second standalone instance takes the next free port from each pool; it does not reuse the first instance’s ports:
On a small VM, lower all three heaps to keep the three JVMs inside memory:
Re-running install without --force is a no-op that reports the current state. With --force, pgcli rewrites namesrv.conf, broker.conf and rmq-proxy.json, recreates the three containers and keeps the broker and controller stores.
Multi-host cluster
Cluster mode uses RocketMQ 5.x’s controller mode: the controller is embedded in every NameServer as a DLedger (Raft) group, and controller-mode brokers elect a master and fail over automatically. Every host runs its own pg addon install rocketmq; pgcli never SSHes to other hosts.
Requirements:
- The same
--clustername on every host. - A unique
--controller-idper host (n0,n1,n2, …). - That host’s
--advertise-hostas a concrete non-loopback IPv4 address. --peer ID@HOSTentries for the other controller members. Pass the full peer set on every host; the local peer is added automatically.- The fixed cluster ports free on every host:
9876,9877,10911,10912,8080and8081. One clustered RocketMQ instance per host. - At least 3 members for fault tolerance. The DLedger quorum is the majority, so 2 members tolerate no failure; pgcli prints a warning for a 2-member cluster.
Install the members one host at a time. For three hosts 10.0.0.11, 10.0.0.12 and 10.0.0.13:
The first two installs are expected to finish with a warning such as:
This is normal: the controller quorum only forms once a majority of NameServers is up. The install still exits successfully and leaves the containers running. After the third member is installed, the controller elects the broker master and the broker registers.
Check every member:
status shows the three container states, the controller id, the full peer list and — when the cluster is reachable — how many brokers are registered and how many are masters. cluster status prints the raw clusterList table; the controller’s BID column (labelled BrokerId in older clients) is 0 for the current master and non-zero for replicas:
The column layout and row order are produced by mqadmin and may differ slightly between 5.x releases; pgcli only relies on the cluster name and broker id columns.
Failover
When the master broker stops, the controller elects another in-sync replica after a heartbeat timeout. Clients that connect through the proxy or NameServer retry automatically. To watch a failover:
enableElectUncleanMaster=false is rendered, so a replica that is not in the in-sync state set is not elected. If the controller quorum itself loses its majority (for example two of three NameServers are down), no master can be elected and writes stop until the quorum returns. Stopping or removing a member does not rewrite the peer lists on the remaining hosts; pgcli never contacts the other nodes.
Ports
| Port | Role | Standalone | Cluster |
|---|---|---|---|
9876 |
NameServer client/RPC | auto, base 9876 |
fixed |
9877 |
Embedded DLedger controller | not used | fixed |
10911 |
Broker listen | auto, base 10911 |
fixed |
10912 |
Broker HA replication | broker_port + 1 |
fixed |
10909 |
Broker VIP | broker_port - 2 |
fixed |
8080 |
Proxy remoting | auto, base 8080 |
fixed |
8081 |
Proxy gRPC | auto, base 8081 |
fixed |
Standalone instances can coexist on one host because every port is drawn from a pool and reserved together with the derived HA/VIP ports. In cluster mode all of these ports are fixed because the controller membership and broker addresses are baked into every node’s config.
Clients
The proxy is the single client entry point in both modes and runs in CLUSTER mode:
- 5.x gRPC SDK (the recommended 5.x client): connect to
<advertise-host>:8081. - Remoting SDK (4.x-style clients): connect to
<advertise-host>:8080, or directly to the broker on<advertise-host>:10911. - NameServer addresses (
9876, controller9877) are internal cluster plumbing. Do not expose them to remote clients.
A standalone instance defaults to 127.0.0.1, so a client on another host needs an install with --advertise-host set to the host’s reachable IP. In cluster mode every member requires a non-loopback IPv4 --advertise-host and the proxy on each host advertises that host.
Topics and messages
Topic auto-creation is enabled (autoCreateTopicEnable=true) for compatibility, but explicit creation is recommended so queue counts are deterministic:
topic create creates the topic across the cluster (-c <cluster-or-name>) with --queues read and write queues (default 3). topic list hides RocketMQ’s internal topics (%RETRY%…, %DLQ%…, TBW102, SELF_TEST_TOPIC, transaction/schedule/trace topics, the 5.x rmq_sys_* / RMQ_SYS_* topics, *_REPLY_TOPIC and the topic named after the cluster); pass --system to show everything. topic describe prints the per-broker queue and offset table from topicStatus.
Send a message and look it up by key:
send prints the sendMessage result, including the message id, send status and queue. Pull messages back with a bounded debug consumer:
consume runs mqadmin consumeMessage in a throwaway container and prints messages to the terminal. It drains the topic’s queues and exits; --timeout (default 30s) is a hard safety limit enforced inside the container, and Ctrl-C stops early. It is a pull-only debug viewer: it does not delete messages and does not commit consumer offsets.
--count is mqadmin’s message budget (default 10); mqadmin accounts it per queue, so a run can print slightly fewer messages than requested. --count 0 removes the budget. --queue/--offset read one queue and use the instance’s broker name (--broker overrides it). --begin/--end accept epoch milliseconds or yyyy-MM-dd#HH:mm:ss:SSS; mqadmin converts the boundaries to queue offsets, so the end of the window can include the first message at or after it.
Deleting a topic removes all of its messages and asks for confirmation unless --yes is passed:
Message retention
Consumption never deletes messages. The broker removes whole commitlog segments (the storage unit shared by all topics on that broker) when a segment is older than fileReservedTime hours and the clock reaches one of the deleteWhen hours, or earlier when disk usage exceeds diskMaxUsedSpaceRatio percent. Retention is broker-wide, not per topic.
Show the running broker’s effective values and change them:
Defaults are 72 hours, 04 o’clock and 75 percent. set requires at least one of --hours (1–8760), --delete-when (one or more hours 0–23 separated by ;) and --disk-ratio (1–100). It applies the change to the running broker with updateBrokerConfig and writes the same values to pg.yaml and the rendered broker.conf, so the setting survives pg addon stop/start without a recreate. An expired segment is not deleted at the exact hour; the broker removes it during the next scheduled cleanup. Raising the ratio above the current disk usage stops disk-pressure deletions.
Retention is stored per broker. In a cluster, run the command on every member host; each broker cleans only its own commitlog.
Delivery and durability
Standalone. The broker is the only node (brokerId=0, brokerRole=ASYNC_MASTER) with no replicas. Messages are written to the broker store under data/broker, so a graceful stop/start keeps them. The rendered disk flush policy is RocketMQ’s default ASYNC_FLUSH; a host power loss can therefore lose the most recent writes. For stronger durability, render SYNC_FLUSH (at the cost of throughput):
Cluster. Brokers replicate in controller mode. pgcli renders allAckInSyncStateSet=true and minInSyncReplicas=2 for 3 or more members (1 for a 2-member cluster), so a produce succeeds only when every in-sync replica has accepted the message. Disk flush is still ASYNC by default; use flushDiskType=SYNC_FLUSH when a power loss must not lose acknowledged writes across all replicas.
Replication protects against a broker failure while the controller quorum is healthy. It does not make the controller store disposable: data/controller holds the DLedger state and epoch files. Deleting it, wiping a member, or reinstalling with --clean-data destroys that member’s controller state and can break the quorum. A member that is removed and rejoined must start with a fresh data directory and the same cluster/controller/peer identity.
pg addon remove rocketmq --clean-data deletes the instance directory (configs, broker store, controller store and logs) and a distinct custom data directory. Without --clean-data, the data and config directories are kept.
Configuration, upgrades and immutability
- Mutable with
--force: version, JVM heaps, broker.conf overrides and, for standalone instances, the listener ports.--config-optionreplaces the stored override map, so pass every override again on a forced reinstall. - Immutable even with
--force: in cluster mode--cluster,--controller-id,--advertise-host,--peerand the fixed ports. These values are embedded in every peer’s configuration; changing them in place is rejected. - Topology changes require a rebuild: standalone ↔ cluster is not an in-place change. Remove the instance with
--clean-dataand install it again in the desired mode. - Custom data directory: pointing
--data-dirat a new path makes the instance use a new, empty store; pgcli does not migrate existing data.
Managed broker.conf keys (rejected in --config-option) include brokerClusterName, brokerName, brokerId, brokerRole, brokerIP1/brokerIP2, listenPort, haListenPort, namesrvAddr, enableControllerMode, controllerAddr, every controller* key, storePathRootDir, storePathCommitLog, storePathEpochFile, autoCreateTopicEnable, allAckInSyncStateSet, minInSyncReplicas, enableControllerInNamesrv, enableElectUncleanMaster and notifyBrokerRoleChanged.
Lifecycle, logs and autostart
Stopping walks the containers in reverse (proxy → broker → namesrv); starting walks them forward (namesrv → broker → proxy). In cluster mode, start does not wait for the full controller quorum: when a majority is not yet reachable the broker stays in its waiting state and the command still succeeds. Check pg addon rocketmq status and cluster status after the other members are up.
Autostart is available like the other top-level addons:
It re-renders the three configs and starts the containers in order. For a cluster member, autostart does not wait for the controller quorum, so members can boot in any order. pg addon start (the global autostart starter) behaves the same way.
Limitations
- No authentication, TLS or ACL. Restrict the network; the proxy and NameServer are open to anyone who can reach them.
- No web UI. Use
pg addon rocketmq status,cluster status, topic commands and the logs. - No online scaling or rolling upgrade. Cluster membership and fixed ports are immutable; member changes require a planned rebuild. The controller store must not be deleted while the member participates in a quorum.
- 2-member clusters have no fault tolerance. Use 3 or more members for production.
- Linux only. The addon relies on host networking and the official image’s
uid/gid 3000. - No message migration, consumer-group management or broker/storage rebalancing. Use the standard RocketMQ administration tools through
pg addon rocketmq shell.