Message Bus Architecture
The Hummingbird message bus is an event-driven architecture built on AWS SNS. Events from multiple sources flow through a central topic, enabling subscribers to filter and process only the events they need.
Architecture
flowchart TD
subgraph Publishers
GL[GitLab Webhooks]
K8S[Kubernetes Clusters]
end
subgraph MessageBus [Message Bus]
SNS[(SNS Topic)]
end
subgraph Archiver
ARCH[SNS S3 Archiver]
S3[(S3 Bucket)]
end
subgraph StatusDB [Status Database]
SQS1[SQS Queue]
WORKER[hummingbird-status]
PG[(PostgreSQL)]
end
subgraph ConsumerQueue [Consumer Queue]
SQS2[SQS Queue]
end
subgraph Consumers
CONSUMER[Event Consumer]
end
GL -->|gitlab-event-forwarder| SNS
K8S -->|kubernetes-event-forwarder| SNS
SNS --> ARCH
ARCH --> S3
SNS --> SQS1
SQS1 --> WORKER
WORKER --> PG
SNS --> SQS2
SQS2 -->|new events| CONSUMER
S3 -.->|historic events| CONSUMER
PG -.->|aggregated status| CONSUMER
Components
| Component | Role | Description |
|---|---|---|
| hummingbird-events-topic | Infrastructure | Central SNS topic for all events |
| gitlab-event-forwarder | Publisher | Receives GitLab webhooks, publishes to SNS |
| kubernetes-event-forwarder | Publisher | Watches K8s resources, publishes changes to SNS |
| sns-s3-archiver | Subscriber | Archives all events to S3 for querying/replay |
| hummingbird-status | Subscriber | Ingests events to PostgreSQL for structured queries |
Message Format
All messages include standard attributes for filtering:
| Attribute | Description | Examples |
|---|---|---|
source |
Event origin | gitlab, kubernetes |
event_type |
Type of event | push, merge_request, ADDED, MODIFIED |
Additional attributes vary by source - see individual publisher docs for details.
GitLab Events
Published by gitlab-event-forwarder:
| Attribute | Description | Example |
|---|---|---|
project_path |
Full project path | redhat/hummingbird/containers |
group_path |
Full group path | redhat/hummingbird |
Kubernetes Events
Published by kubernetes-event-forwarder:
| Attribute | Description | Example |
|---|---|---|
cluster |
API server URL | https://api.cluster:6443 |
namespace |
Object namespace | production |
kind |
Resource kind | Pod, Deployment |
api_version |
API version | v1, apps/v1 |
object_name |
Resource name | nginx-7d8c4c9d6f |
Subscription Filtering
SNS filter policies enable subscribers to receive only relevant events:
{
"source": ["gitlab"],
"event_type": ["push", "merge_request"]
}
{
"source": ["kubernetes"],
"kind": ["Deployment"],
"event_type": ["MODIFIED"]
}
See hummingbird-events-topic for subscription setup instructions.
Event Flow Example
- Developer pushes to GitLab repository
- GitLab sends webhook to gitlab-event-forwarder Lambda
- Lambda validates token, extracts metadata, publishes to SNS
- SNS delivers to all matching subscribers:
- sns-s3-archiver stores event in S3
- Event consumers process new events in real-time
Consuming Events
Consumers can receive events from multiple sources:
- New events: Subscribe to SNS topic for real-time processing
- Historic events: Download from S3 archive for replay or catch-up
- Structured queries: Query PostgreSQL via hummingbird-status for pipeline status, component state, and cross-referenced data
The S3 archive enables consumers to bootstrap state, then switch to live SNS events. The PostgreSQL database provides a queryable view of pipeline status with relationships between pushes, builds, snapshots, and releases.
Replaying Events
The sns-s3-archiver stores complete SNS records with decoded payloads, enabling easy replay:
# Download archived events
aws s3 sync s3://bucket-name/2025/12/13/ ./local-events/
# Browse events
zcat ./local-events/2025/12/13/12/34/*.json.gz | jq
import gzip
import json
from pathlib import Path
# Replay archived events to handler
for path in sorted(Path("./local-events").rglob("*.json.gz")):
with gzip.open(path, "rt") as f:
sns_record = json.load(f)
event = {"Records": [{"Sns": sns_record}]}
my_handler.lambda_handler(event, None)
See sns-s3-archiver documentation for details on storage format and
the _decode_message pattern for handlers.