Operator Events
Operator events let you subscribe to lifecycle events from your Outpost deployment, including delivery failures, destination disabling, retry exhaustion, and subscription changes.
Configuration
Enable operator events by specifying topics and configuring a sink.
Topics
Configure operator event topic subscriptions through Hookdeck Monitoring settings or Config API.
Set OPERATION_EVENTS_TOPICS to a comma-separated list of topics:
OPERATION_EVENTS_TOPICS=alert.destination.disabled,alert.attempt.exhausted_retries
Use * to subscribe to all topics. A wildcard subscription also includes topics added in future versions, so upgrading Outpost can change what your sink receives. Prefer an explicit topic list unless your sink is sized for per-attempt volume.
Available topics:
| Topic | Trigger |
|---|---|
alert.destination.consecutive_failure | Consecutive failure count reaches 50%, 70%, 90%, or 100% of ALERT_CONSECUTIVE_FAILURE_COUNT |
alert.destination.disabled | Destination auto-disabled at 100% failure threshold |
alert.attempt.exhausted_retries | Delivery exhausts all retry attempts (at most one alert per destination within the deduplication window) |
attempt.success | Every successful delivery attempt |
attempt.failed | Every failed delivery attempt, including retries |
tenant.subscription.updated | Destination created/updated/deleted and tenant topics or destination count changed |
Operator event delivery and topic selection are managed through Hookdeck Monitoring settings.
If OPERATION_EVENTS_TOPICS is empty or unset, operator events are disabled. If topics are configured but no sink is set, Outpost fails to start.
Sinks
Configure exactly one sink to receive events.
Configure sinks for operator event forwarding in Hookdeck Monitoring settings.
Four sink types are supported:
HTTP
Sends events as POST requests to a URL. If OPERATION_EVENTS_HTTP_SIGNING_SECRET is set, requests are signed with HMAC-SHA256.
OPERATION_EVENTS_HTTP_URL=https://example.com/outpost-events
OPERATION_EVENTS_HTTP_SIGNING_SECRET=your-secret
The HTTP sink sends signatures in X-Outpost-Signature:
- Format:
v0=<hex> - Algorithm: HMAC-SHA256 over the raw JSON body
Verification example:
import hashlib
import hmac
expected = hmac.new(signing_secret.encode(), body, hashlib.sha256).hexdigest()
assert signature_header == f"v0={expected}"
AWS SQS
OPERATION_EVENTS_AWS_SQS_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/123456789/outpost-events
OPERATION_EVENTS_AWS_SQS_ACCESS_KEY_ID=AKIA...
OPERATION_EVENTS_AWS_SQS_SECRET_ACCESS_KEY=...
OPERATION_EVENTS_AWS_SQS_REGION=us-east-1
OPERATION_EVENTS_AWS_SQS_ENDPOINT= # optional, for local dev
GCP Pub/Sub
OPERATION_EVENTS_GCP_PUBSUB_PROJECT_ID=my-project
OPERATION_EVENTS_GCP_PUBSUB_TOPIC_ID=outpost-events
OPERATION_EVENTS_GCP_PUBSUB_CREDENTIALS={"type":"service_account",...}
RabbitMQ
OPERATION_EVENTS_RABBITMQ_SERVER_URL=amqp://guest:guest@localhost:5672
OPERATION_EVENTS_RABBITMQ_EXCHANGE=outpost-events
Event Envelope
All operator events share this envelope:
{
"id": "unique-event-id",
"topic": "alert.destination.consecutive_failure",
"time": "2025-06-01T12:00:00Z",
"deployment_id": "my-deployment",
"tenant_id": "tenant_123",
"data": {}
}
| Field | Description |
|---|---|
id | Unique event identifier |
topic | Event topic |
time | ISO 8601 timestamp |
deployment_id | Deployment ID (if configured) |
tenant_id | Tenant associated with the event (if applicable) |
data | Topic-specific payload |
Event Payloads
alert.destination.consecutive_failure
Emitted when a destination reaches 50%, 70%, 90%, or 100% of ALERT_CONSECUTIVE_FAILURE_COUNT.
{
"tenant_id": "tenant_123",
"event": {},
"attempt": {},
"destination": {
"id": "des_456",
"tenant_id": "tenant_123",
"type": "webhook",
"topics": ["order.created"],
"disabled_at": null
},
"consecutive_failures": {
"current": 50,
"max": 100,
"threshold": 50
}
}
alert.destination.disabled
Emitted when a destination is auto-disabled after reaching the 100% threshold (only when ALERT_AUTO_DISABLE_DESTINATION=true).
{
"tenant_id": "tenant_123",
"destination": {
"id": "des_456",
"tenant_id": "tenant_123",
"type": "webhook",
"topics": ["order.created"],
"disabled_at": "2025-06-01T12:00:00Z"
},
"disabled_at": "2025-06-01T12:00:00Z",
"reason": "consecutive_failure",
"event": {},
"attempt": {}
}
alert.attempt.exhausted_retries
Emitted when a delivery exhausts all retry attempts. At most one alert per destination within ALERT_EXHAUSTED_RETRIES_WINDOW_SECONDS; the alert payload carries the first exhausted event in the window. Set the window to 0 to alert on every exhaustion.
{
"tenant_id": "tenant_123",
"event": {},
"attempt": {},
"destination": {
"id": "des_456",
"tenant_id": "tenant_123",
"type": "webhook",
"topics": ["order.created"],
"disabled_at": null
}
}
attempt.success / attempt.failed
Emitted once per delivery attempt, keyed by outcome. The two topics share one payload shape; attempt.status carries the outcome. attempt.failed fires on every failed attempt including retries — use attempt.attempt_number and event.eligible_for_retry to distinguish retryable failures from final ones.
{
"tenant_id": "tenant_123",
"event": {
"id": "evt_789",
"tenant_id": "tenant_123",
"destination_id": "des_456",
"matched_destination_ids": ["des_456"],
"topic": "order.created",
"eligible_for_retry": true,
"time": "2025-06-01T12:00:00Z",
"metadata": {},
"data": {
"order_id": "ord_123"
}
},
"attempt": {
"id": "att_abc",
"tenant_id": "tenant_123",
"event_id": "evt_789",
"destination_id": "des_456",
"destination_type": "webhook",
"attempt_number": 2,
"manual": false,
"status": "failed",
"time": "2025-06-01T12:00:05Z",
"code": "500",
"response_data": {
"status": 500,
"body": "internal server error"
}
},
"destination": {
"id": "des_456",
"tenant_id": "tenant_123",
"type": "webhook",
"topics": ["order.created"],
"disabled_at": null
}
}
An attempt.success payload is identical except attempt.status is "success" and code/response_data carry the destination's response (for a webhook, the HTTP status and body). For network-level failures, code is an error class such as connection_refused or dns_error instead of an HTTP status.
The alert payloads above carry the same event and attempt objects, elided for brevity.
tenant.subscription.updated
Emitted when destination changes affect tenant-level subscribed topics or destination count.
{
"tenant_id": "tenant_123",
"topics": ["order.created", "order.updated"],
"previous_topics": ["order.created"],
"destinations_count": 3,
"previous_destinations_count": 2
}
Delivery Guarantees
alert.* and attempt.* topics are delivered with an at-least-once guarantee. For other topics (e.g. tenant.subscription.updated), delivery is on a best-effort basis with up to 3 attempts. Consumers should deduplicate using the event id.
Related Configuration
Alert threshold and destination auto-disable behavior are managed through Hookdeck Monitoring settings.
| Config | Description | Default |
|---|---|---|
ALERT_CONSECUTIVE_FAILURE_COUNT | Number of consecutive failures before the 100% threshold | 100 |
ALERT_AUTO_DISABLE_DESTINATION | Auto-disable destinations at the 100% threshold | false |
ALERT_EXHAUSTED_RETRIES_WINDOW_SECONDS | Deduplication window for exhausted retry alerts (seconds) | 3600 |