Abstract Backend
Abstract Backend is a pluggable abstraction layer for backend components. It defines shared contracts, runtime helpers, and discovery utilities so that individual backends can be added or removed with nothing more than pip install or pip uninstall.
Instead of hard-wiring a specific queue, cache, or service implementation into your application, Abstract Backend lets you:
- Keep a stable Python API for your code (
MessageQueueBackend,EventConsumer, etc.). - Discover concrete implementations from Python entry points.
- Swap implementations at deploy time without changing application code.
Why a backend abstraction layer?β
Building multi-environment systems usually forces developers to pick one message broker or service vendor early, even when the project would benefit from a pluggable architecture. Abstract Backend removes that friction:
- Hot-swappable backends β Install a backend provider package (for example
abe-backend-redis) and Abstract Backend will discover it automatically via theabe.backends.message_queueentry point group. - Simple deprecation story β Removing a backend is as easy as
pip uninstallor replacing the package with another provider. - Strong typing & protocols β The interfaces in
abe/backends/message_queue/base/are Protocol-based so your IDE and static analysis tools know what to expect. - Out-of-the-box fallback β An in-memory
MemoryBackendlives inabe/backends/message_queue/service/memory.pyso you can get started instantly while evaluating production options.
Core building blocksβ
| Component | Location | Purpose |
|---|---|---|
MessageQueueBackend protocol | abe/backends/message_queue/base/protocol.py | Defines the async publish/consume contract that every backend must implement. |
EventConsumer protocol & AsyncLoopConsumer | abe/backends/message_queue/base/consumer.py, abe/backends/message_queue/consumer.py | Provides a standard message-consumption loop that works with any backend. |
| Plugin loader | abe/backends/message_queue/loader.py | Discovers implementations via Python entry points and selects the right backend at runtime. |
| Memory backend | abe/backends/message_queue/service/memory.py | Development-friendly backend used when no external provider is installed. |
The combination of protocols, loader, and runtime helpers gives you a consistent interface for publishing and consuming messages across environments.
How discovery worksβ
- You install one or more backend provider packages. Each provider registers an entry point under
abe.backends.message_queue. - Your application calls
load_backend(). - The loader selects the requested provider (via
QUEUE_BACKENDenvironment variable) or the first non-memory option. - The providerβs
from_env()factory initializes the backend using deployment-specific settings.
Developer experience highlightsβ
- One API, many providers β Application code targets the
MessageQueueBackendinterface and does not need to know which provider is installed. - Pip-based lifecycle β Install a backend you need, remove the ones you do not. CI/CD pipelines can manage providers with standard Python packaging tooling.
- Observability hooks β Logging configuration under
abe/logging/exposesLoggingConfigand helper utilities to standardize log output across backends. - Typed surface area β
abe/types.pyexports shared type aliases, ensuring downstream projects receive full typing metadata thanks to the bundledpy.typedmarker.
Typical flow for consumersβ
from abe.backends.message_queue.loader import load_backend
from abe.backends.message_queue.consumer import AsyncLoopConsumer
async def handle_message(payload: dict[str, object]) -> None:
... # implement domain logic
backend = load_backend() # resolves to the installed message-queue provider
consumer = AsyncLoopConsumer(backend)
await consumer.run(handle_message)
Change the behavior simply by installing a different backend provider package or exporting QUEUE_BACKEND=my-provider before the process starts.
When is Abstract Backend a good fit?β
- You support multiple deployment environments that depend on different queue technologies.
- You ship a library that needs to integrate with user-selected infrastructure without baking in a dependency.
- You want to experiment with new providers without rewriting glue code.
- You care about typed interfaces and predictable runtime lifecycle management.
Next stepsβ
- Set up your environment β Quick Start
- Learn about entry-point validation β Type Checking with MyPy
- Dive into architecture details β Architecture Overview
Bring your own backend package or build one that implements the protocols. Abstract Backend makes it pleasant to wire everything together.