Route Messages to Handlers with a Python Dict

This code demonstrates a simple message routing pattern using a dictionary to map topic keys to handler functions, with a default handler for unmatched topics.

Easy Python 3.9+ Aug 9, 2026 System design patterns 12 views 0 copies

Python code

35 lines
Python 3.9+
def route_message(message, routing_table):
    """Route a message to the correct handler based on the topic key."""
    topic = message.get("topic", "default")
    handler = routing_table.get(topic, routing_table.get("default"))
    return handler(message)


def handle_orders(message):
    return f"Orders handler processed: {message['payload']}"


def handle_payments(message):
    return f"Payments handler processed: {message['payload']}"


def handle_unknown(message):
    return f"Default handler processed: {message['payload']}"


if __name__ == "__main__":
    routing_table = {
        "orders": handle_orders,
        "payments": handle_payments,
        "default": handle_unknown,
    }

    messages = [
        {"topic": "orders", "payload": {"id": 1, "item": "Widget"}},
        {"topic": "payments", "payload": {"id": 1, "amount": 19.99}},
        {"topic": "inventory", "payload": {"id": 1, "stock": 10}},
        {"payload": {"action": "unknown"}},
    ]

    for msg in messages:
        print(route_message(msg, routing_table))

Output

stdout
Orders handler processed: {'id': 1, 'item': 'Widget'}
Payments handler processed: {'id': 1, 'amount': 19.99}
Default handler processed: {'id': 1, 'stock': 10}
Default handler processed: {'action': 'unknown'}

How it works

The route_message function uses the topic key from the message to look up the corresponding handler in the routing_table dictionary. If the topic is missing or not found, it falls back to the 'default' handler, ensuring every message is processed. This pattern decouples message sources from their processing logic, making it easy to add new topics by simply extending the dictionary. The handlers are plain functions that receive the full message, allowing them to access any part of the message payload.

Common mistakes

  • Forgetting to include a 'default' key causes KeyError for unknown topics.
  • Assuming the message always has a 'topic' key without using .get().
  • Passing the wrong type of handler (e.g., storing strings instead of callables).

Variations

  1. Use a class-based approach where handlers are methods and routing_table maps topics to method names.
  2. Use a dictionary of lambdas for simple inline handling logic.

Real-world use cases

  • In a microservices event bus, route incoming events to different processing services based on event type.
  • In a message queue consumer, dispatch messages to different worker functions for order processing, payment, and inventory.
  • In a plugin architecture, allow dynamic registration of new handlers by updating the routing table at runtime.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from System design patterns

Related tutorials and quizzes for this topic.