Integrating RabbitMQ Routing Keys with AMPS
This page assumes a bridge, adapter, or application republishes messages from RabbitMQ into AMPS while preserving the original routing key in the AMPS topic name or in a message field. That approach preserves familiar routing-key patterns while using AMPS as the queryable, stateful layer for dashboards, operational tooling, and interactive applications. The same conventions also keep a straightforward path for applications that later publish directly into AMPS.
Where RabbitMQ and AMPS Overlap
RabbitMQ topic exchanges and AMPS both route messages by topic-like names. AMPS can preserve RabbitMQ wildcard patterns by using TopicMatchingPolicy set to rabbitmq as the instance default or as a local override on the imported routing-key space. Subscriptions and SOW queries can also use topic_matching_policy=rabbitmq, and any TOPIC_MATCH predicate in the same command filter uses RabbitMQ wildcard rules.
That overlap makes lift-and-shift integration simpler. A bridge can preserve routing keys such as audit.ops.user or orders.eu.priority, and AMPS can then add capabilities that are useful for observability and UI work:
- Persistent current state through the State of the World (SOW)
- Atomic initial load plus live updates through
sow_and_subscribe - Lower-bandwidth browser updates through
sow_and_delta_subscribe - Server-managed rollups with Views and Unions
- UI-friendly refresh rates with ConflatedTopics
RabbitMQ Patterns Compared to Default AMPS PCRE
The default AMPS topic matching policy is pcre, which uses full regular expressions. RabbitMQ syntax is simpler and maps directly to routing-key semantics.
| RabbitMQ Pattern | Meaning | Representative PCRE Equivalent |
|---|---|---|
audit.*.user | Match exactly one word between audit and user | ^audit\.[^.]+\.user$ |
audit.#.user | Match zero or more words between audit and user | ^audit(\.[^.]+)*\.user$ |
# | Match every routing key | .* |
Under rabbitmq, only * and # are wildcards, and . is the routing-key separator. Constructs such as ^, $, and .* are PCRE syntax, not RabbitMQ syntax.
Recommended AMPS Design
For most RabbitMQ integrations, the cleanest AMPS design looks like this:
- Preserve the original RabbitMQ routing key when the bridge publishes into AMPS.
- Keep the instance default at
pcreunless most of the instance uses RabbitMQ semantics. For imported routing-key spaces, addTopicMatchingPolicyset torabbitmqbeside eachPatternorUnderlyingTopicthat should use RabbitMQ rules. - Capture the relevant routing-key space into a Pattern topic so AMPS maintains current state per logical routing key without a separate SOW topic definition for each key.
- Build a Union whose
UnderlyingTopicrepeats that same pattern expression when dashboards or downstream services need one consolidated SOW topic. - Build Views and ConflatedTopics on top of that union for operator dashboards and UI refresh.
This layout works well for phased coexistence and for direct AMPS adoption later because the topic model presented to applications stays stable.
A Pattern topic cannot be used directly as the underlying source for a View. Use a Union first, with the same pattern expression in the Union UnderlyingTopic, then place the View or ConflatedTopic on top of the Union.
Sample Configuration
The following example keeps the instance default at pcre, preserves a RabbitMQ audit namespace inside AMPS with local RabbitMQ overrides, rolls it into a single SOW topic for analytics, and then produces a dashboard-oriented topic:
<AMPSConfig>
<Name>rabbitmq-observability</Name>
<TopicMatchingPolicy>pcre</TopicMatchingPolicy>
<SOW>
<Topic>
<Name>rabbitmq-audit-space</Name>
<Pattern>audit.#</Pattern>
<TopicMatchingPolicy>rabbitmq</TopicMatchingPolicy>
<MessageType>json</MessageType>
<Key>/eventId</Key>
<FileName>./sow/%n.sow</FileName>
</Topic>
<Union>
<Name>rabbitmq-audit-union</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>audit.#</UnderlyingTopic>
<TopicMatchingPolicy>rabbitmq</TopicMatchingPolicy>
</Union>
<View>
<Name>rabbitmq-audit-by-service</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>rabbitmq-audit-union</UnderlyingTopic>
<Projection>
<Field>/service</Field>
<Field>COUNT(/eventId) AS /eventCount</Field>
</Projection>
<Grouping>
<Field>/service</Field>
</Grouping>
</View>
<ConflatedTopic>
<Name>rabbitmq-audit-by-service-ui</Name>
<MessageType>json</MessageType>
<UnderlyingTopic>rabbitmq-audit-by-service</UnderlyingTopic>
<Interval>1s</Interval>
</ConflatedTopic>
</SOW>
</AMPSConfig>
If you truly want to capture the entire RabbitMQ topic-exchange namespace, use # as the Pattern. In practice, most teams use a bounded namespace such as audit.# or orders.# so entitlements, monitoring, and disk planning stay predictable.
Usage Tips
- Use
TOPIC_MATCHwhen a field stores the original routing key. For example,/routingKey TOPIC_MATCH 'audit.#.user'applies RabbitMQ wildcard rules to the field value. - Migrating clients can keep RabbitMQ wildcard syntax on a per-request basis with
topic_matching_policy=rabbitmqon commands such assubscribe,sow, andsow_and_subscribe. - Use
LIKEonly when you intentionally want PCRE behavior regardless of the resolved topic policy. - Choose the SOW key from the business entity, not from the routing key alone, when one routing key can carry repeated updates for the same object.
- Use
sow_and_subscribeagainst the Union or View to hydrate an operator screen atomically, then keep it up to date without a query gap. - Use
sow_and_delta_subscribeor aConflatedTopicfor browser-based dashboards that do not need every intermediate update.