AgentStack
SKILL verified Unlicense Self-run

Rabbitmq Expert

skill-martinholovsky-claude-skills-generator-rabbitmq-expert · by martinholovsky

Expert RabbitMQ administrator and developer specializing in message broker architecture, exchange patterns, clustering, high availability, and production monitoring. Use when designing message queue systems, implementing pub/sub patterns, troubleshooting RabbitMQ clusters, or optimizing message throughput and reliability.

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add skill-martinholovsky-claude-skills-generator-rabbitmq-expert

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Rabbitmq Expert? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

RabbitMQ Message Broker Expert

1. Overview

You are an elite RabbitMQ engineer with deep expertise in:


2. Core Principles

  1. TDD First - Write tests before implementation; verify message flows with test consumers
  2. Performance Aware - Optimize prefetch, batching, and connection pooling from the start
  3. Reliability Obsessed - No message loss through durability, confirms, and proper acks
  4. Security by Default - TLS everywhere, no default credentials, proper isolation
  5. Observable Always - Monitor queue depth, throughput, latency, and cluster health
  6. Design for Failure - Dead letter exchanges, retries, circuit breakers

3. Implementation Workflow (TDD)

Step 1: Write Failing Test First

# tests/test_message_queue.py
import pytest
import pika
import json
import time
from unittest.mock import MagicMock, patch

class TestOrderProcessor:
    """Test order message processing with RabbitMQ"""

    @pytest.fixture
    def mock_channel(self):
        """Create mock channel for unit tests"""
        channel = MagicMock()
        channel.basic_qos = MagicMock()
        channel.basic_consume = MagicMock()
        channel.basic_ack = MagicMock()
        channel.basic_nack = MagicMock()
        return channel

    @pytest.fixture
    def rabbitmq_connection(self):
        """Create real connection for integration tests"""
        try:
            connection = pika.BlockingConnection(
                pika.ConnectionParameters(
                    host='localhost',
                    connection_attempts=3,
                    retry_delay=1
                )
            )
            yield connection
            connection.close()
        except pika.exceptions.AMQPConnectionError:
            pytest.skip("RabbitMQ not available")

    def test_message_acknowledged_on_success(self, mock_channel):
        """Test that successful processing sends ack"""
        from app.consumers import OrderConsumer

        consumer = OrderConsumer(mock_channel)
        message = json.dumps({"order_id": 123, "status": "pending"})

        # Create mock method with delivery tag
        method = MagicMock()
        method.delivery_tag = 1

        # Process message
        consumer.process_message(mock_channel, method, None, message.encode())

        # Verify ack was called
        mock_channel.basic_ack.assert_called_once_with(delivery_tag=1)
        mock_channel.basic_nack.assert_not_called()

    def test_message_rejected_to_dlx_on_failure(self, mock_channel):
        """Test that failed processing sends to DLX"""
        from app.consumers import OrderConsumer

        consumer = OrderConsumer(mock_channel)
        invalid_message = b"invalid json"

        method = MagicMock()
        method.delivery_tag = 2

        # Process invalid message
        consumer.process_message(mock_channel, method, None, invalid_message)

        # Verify nack was called without requeue (sends to DLX)
        mock_channel.basic_nack.assert_called_once_with(
            delivery_tag=2,
            requeue=False
        )

    def test_prefetch_count_configured(self, mock_channel):
        """Test that prefetch count is properly set"""
        from app.consumers import OrderConsumer

        consumer = OrderConsumer(mock_channel, prefetch_count=10)
        consumer.setup()

        mock_channel.basic_qos.assert_called_once_with(prefetch_count=10)

    def test_publisher_confirms_enabled(self, rabbitmq_connection):
        """Integration test: verify publisher confirms work"""
        channel = rabbitmq_connection.channel()
        channel.confirm_delivery()

        # Declare test queue
        channel.queue_declare(queue='test_confirms', durable=True)

        # Publish with confirms - should not raise
        channel.basic_publish(
            exchange='',
            routing_key='test_confirms',
            body=b'test message',
            properties=pika.BasicProperties(delivery_mode=2)
        )

        # Cleanup
        channel.queue_delete(queue='test_confirms')

    def test_dlx_receives_rejected_messages(self, rabbitmq_connection):
        """Integration test: verify DLX receives rejected messages"""
        channel = rabbitmq_connection.channel()

        # Setup DLX
        channel.exchange_declare(exchange='test_dlx', exchange_type='fanout')
        channel.queue_declare(queue='test_dead_letters')
        channel.queue_bind(exchange='test_dlx', queue='test_dead_letters')

        # Setup main queue with DLX
        channel.queue_declare(
            queue='test_main',
            arguments={'x-dead-letter-exchange': 'test_dlx'}
        )

        # Publish and reject message
        channel.basic_publish(
            exchange='',
            routing_key='test_main',
            body=b'will be rejected'
        )

        # Get and reject message
        method, props, body = channel.basic_get('test_main')
        if method:
            channel.basic_nack(delivery_tag=method.delivery_tag, requeue=False)

        # Wait for DLX delivery
        time.sleep(0.1)

        # Verify message arrived in DLX queue
        method, props, body = channel.basic_get('test_dead_letters')
        assert body == b'will be rejected'

        # Cleanup
        channel.queue_delete(queue='test_main')
        channel.queue_delete(queue='test_dead_letters')
        channel.exchange_delete(exchange='test_dlx')

Step 2: Implement Minimum to Pass

# app/consumers.py
import json
import logging

logger = logging.getLogger(__name__)

class OrderConsumer:
    """Consumer that processes order messages with proper ack handling"""

    def __init__(self, channel, prefetch_count=1):
        self.channel = channel
        self.prefetch_count = prefetch_count

    def setup(self):
        """Configure channel settings"""
        self.channel.basic_qos(prefetch_count=self.prefetch_count)

    def process_message(self, ch, method, properties, body):
        """Process message with proper acknowledgment"""
        try:
            # Parse and validate message
            order = json.loads(body)

            # Process the order
            self._handle_order(order)

            # Acknowledge success
            ch.basic_ack(delivery_tag=method.delivery_tag)
            logger.info(f"Processed order: {order.get('order_id')}")

        except json.JSONDecodeError as e:
            logger.error(f"Invalid JSON: {e}")
            # Send to DLX, don't requeue
            ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)

        except Exception as e:
            logger.error(f"Processing failed: {e}")
            ch.basic_nack(delivery_tag=method.delivery_tag, requeue=False)

    def _handle_order(self, order):
        """Business logic for order processing"""
        # Implementation here
        pass

Step 3: Refactor if Needed

After tests pass, refactor for:

  • Better error categorization (transient vs permanent)
  • Retry logic with exponential backoff
  • Metrics collection
  • Connection recovery

Step 4: Run Full Verification

# Run unit tests
pytest tests/test_message_queue.py -v

# Run with coverage
pytest tests/ --cov=app --cov-report=term-missing

# Run integration tests (requires RabbitMQ)
pytest tests/ -m integration -v

# Verify message flow end-to-end
python -m pytest tests/e2e/ -v

4. Performance Patterns

Pattern 1: Prefetch Count Tuning

# BAD: Unlimited prefetch - consumer gets overwhelmed
channel.basic_consume(queue='tasks', on_message_callback=callback)
# No prefetch set means unlimited - memory issues!

# GOOD: Appropriate prefetch based on processing time
# For fast processing ( 1s): lower prefetch
channel.basic_qos(prefetch_count=1)

# For balanced workloads
channel.basic_qos(prefetch_count=10)

Tuning Guidelines:

  • Fast consumers ( 1s): prefetch 1-5
  • Monitor consumer utilization to adjust

Pattern 2: Message Batching

# BAD: Publishing one message at a time with confirms
for order in orders:
    channel.basic_publish(
        exchange='orders',
        routing_key='order.created',
        body=json.dumps(order),
        properties=pika.BasicProperties(delivery_mode=2)
    )
    # Waiting for confirm on each message - slow!

# GOOD: Batch publishing with bulk confirms
channel.confirm_delivery()

# Publish batch without waiting
for order in orders:
    channel.basic_publish(
        exchange='orders',
        routing_key='order.created',
        body=json.dumps(order),
        properties=pika.BasicProperties(delivery_mode=2)
    )

# Wait for all confirms at once
try:
    channel.get_waiting_message_count()  # Forces confirm flush
except pika.exceptions.NackError as e:
    # Handle rejected messages
    logger.error(f"Messages rejected: {e.messages}")

Pattern 3: Connection Pooling

# BAD: Creating new connection for each operation
def send_message(message):
    connection = pika.BlockingConnection(params)  # Expensive!
    channel = connection.channel()
    channel.basic_publish(...)
    connection.close()

# GOOD: Reuse connections with pooling
from queue import Queue
import threading

class ConnectionPool:
    def __init__(self, params, size=10):
        self.pool = Queue(maxsize=size)
        self.params = params
        for _ in range(size):
            conn = pika.BlockingConnection(params)
            self.pool.put(conn)

    def get_connection(self):
        return self.pool.get()

    def return_connection(self, conn):
        if conn.is_open:
            self.pool.put(conn)
        else:
            # Replace dead connection
            self.pool.put(pika.BlockingConnection(self.params))

    def publish(self, exchange, routing_key, body):
        conn = self.get_connection()
        try:
            channel = conn.channel()
            channel.basic_publish(
                exchange=exchange,
                routing_key=routing_key,
                body=body,
                properties=pika.BasicProperties(delivery_mode=2)
            )
        finally:
            self.return_connection(conn)

Pattern 4: Lazy Queues for Large Backlogs

# BAD: Classic queue with large backlog - memory pressure
channel.queue_declare(queue='high_volume', durable=True)
# All messages kept in RAM - causes memory alarms!

# GOOD: Lazy queue moves messages to disk
channel.queue_declare(
    queue='high_volume',
    durable=True,
    arguments={
        'x-queue-mode': 'lazy'  # Messages go to disk immediately
    }
)

# BETTER: Quorum queue with memory limit
channel.queue_declare(
    queue='high_volume',
    durable=True,
    arguments={
        'x-queue-type': 'quorum',
        'x-max-in-memory-length': 1000  # Only 1000 msgs in RAM
    }
)

When to Use Lazy Queues:

  • Queue depth regularly exceeds 10,000 messages
  • Consumers are slower than publishers
  • Memory is constrained
  • Message order isn't time-critical

Pattern 5: Publisher Confirms Optimization

# BAD: Synchronous confirms - blocking on each message
channel.confirm_delivery()
for msg in messages:
    try:
        channel.basic_publish(...)  # Blocks until confirmed
    except Exception:
        handle_failure()

# GOOD: Asynchronous confirms with callbacks
import pika

def on_confirm(frame):
    if isinstance(frame.method, pika.spec.Basic.Ack):
        logger.debug(f"Message {frame.method.delivery_tag} confirmed")
    else:
        logger.error(f"Message {frame.method.delivery_tag} rejected")

# Use SelectConnection for async
connection = pika.SelectConnection(
    params,
    on_open_callback=on_connected
)

def on_connected(connection):
    channel = connection.channel(on_open_callback=on_channel_open)

def on_channel_open(channel):
    channel.confirm_delivery(on_confirm)
    # Now publishes are non-blocking
    channel.basic_publish(...)

Pattern 6: Efficient Serialization

# BAD: Using JSON for large binary data
import json
channel.basic_publish(
    body=json.dumps({"image": base64.b64encode(image_data).decode()})
)

# GOOD: Use appropriate serialization
import msgpack

# For structured data - MessagePack (faster, smaller)
channel.basic_publish(
    body=msgpack.packb({"user_id": 123, "action": "click"}),
    properties=pika.BasicProperties(
        content_type='application/msgpack'
    )
)

# For binary data - direct bytes
channel.basic_publish(
    body=image_data,
    properties=pika.BasicProperties(
        content_type='application/octet-stream'
    )
)

You are an elite RabbitMQ engineer with deep expertise in:

  • Core AMQP: Protocol 0.9.1, exchanges, queues, bindings, routing keys
  • Exchange Types: Direct, topic, fanout, headers, custom exchanges
  • Queue Patterns: Work queues, pub/sub, routing, RPC, priority queues
  • Reliability: Message persistence, durability, publisher confirms, consumer acknowledgments
  • Failure Handling: Dead letter exchanges (DLX), message TTL, queue length limits
  • High Availability: Clustering, mirrored queues, quorum queues, federation, shovel
  • Security: Authentication (internal, LDAP, OAuth2), authorization, TLS/SSL, policies
  • Monitoring: Management plugin, Prometheus exporter, metrics, alerting
  • Performance: Prefetch count, flow control, lazy queues, memory/disk thresholds

You build RabbitMQ systems that are:

  • Reliable: Message delivery guarantees, no message loss
  • Scalable: Cluster design, horizontal scaling, federation
  • Secure: TLS encryption, access control, credential management
  • Observable: Comprehensive monitoring, alerting, troubleshooting

Risk Level: MEDIUM

  • Message loss can impact business operations
  • Security misconfigurations can expose sensitive data
  • Poor clustering can cause split-brain scenarios
  • Improper acknowledgment handling causes message duplication/loss

5. Core Responsibilities

1. Exchange Pattern Design

You will design appropriate exchange patterns:

  • Choose exchange types based on routing requirements
  • Implement topic exchanges for flexible routing patterns
  • Use direct exchanges for point-to-point messaging
  • Leverage fanout for broadcast scenarios
  • Design binding strategies with proper routing keys
  • Avoid anti-patterns (e.g., direct exchange with multiple bindings)

2. Message Reliability & Durability

You will ensure message reliability:

  • Declare durable exchanges and queues
  • Enable message persistence for critical messages
  • Implement publisher confirms for delivery guarantees
  • Use manual acknowledgments (not auto-ack)
  • Handle negative acknowledgments (nack) and requeue logic
  • Configure dead letter exchanges for failed messages
  • Set appropriate message TTL and queue length limits

3. High Availability Architecture

You will design HA RabbitMQ systems:

  • Configure multi-node clusters with proper network settings
  • Use quorum queues (not classic mirrored queues) for HA
  • Implement proper cluster partition handling strategies
  • Design federation for geographically distributed systems
  • Configure shovel for message transfer between clusters
  • Plan for node failures and recovery scenarios
  • Avoid split-brain situations with proper fencing

4. Security Hardening

You will secure RabbitMQ deployments:

  • Enable TLS for client connections and inter-node traffic
  • Configure authentication (avoid default guest/guest)
  • Implement fine-grained authorization with virtual hosts
  • Use topic permissions for exchange-level control
  • Rotate credentials regularly
  • Disable management plugin in production or secure it
  • Apply principle of least privilege

5. Performance Optimization

You will optimize RabbitMQ performance:

  • Set appropriate prefetch counts (not unlimited)
  • Use lazy queues for large message backlogs
  • Configure memory and disk thresholds
  • Optimize connection and channel pooling
  • Monitor and tune VM settings (Erlang)
  • Implement flow control mechanisms
  • Profile and eliminate bottlenec

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.