Upgrade to v0.16
This guide covers breaking changes and migration steps when upgrading from v0.15 to v0.16.
Breaking Changes Overview
| Change | Impact | Action Required |
|---|---|---|
| Webhook signing secret prefix changed | New webhook destination signing secrets | Set DESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATE to preserve previous behavior |
Event destination_id replaced with matched_destination_ids | Event API responses and queries | Update code that reads destination_id from events to use matched_destination_ids |
| Delivery metadata timestamp format | Consumers of delivery metadata timestamp field | Update timestamp parsing from Unix seconds to ISO 8601 |
| Response data body stored as raw string | Consumers of response_data.body | Update code that treats response_data.body as a parsed JSON object |
| Alert callbacks replaced by operator events | Users of ALERT_CALLBACK_URL | Migrate to OPERATOR_EVENTS_* config |
Webhook Signing Secret Prefix Changed
The default signing secret template for new webhook destinations changed from {{.RandomHex}} to whsec_{{.RandomHex}}. New destinations will now have signing secrets prefixed with whsec_ (e.g., whsec_a1b2c3...).
Existing destinations keep their current signing secrets — this only affects newly created destinations.
Preserving previous behavior
To keep generating unprefixed secrets, set this config var:
Event destination_id Replaced with matched_destination_ids
The destination_id field has been removed from events and replaced with matched_destination_ids, an array of destination IDs that the event was actually routed to.
API response change
v0.15:
json
v0.16:
json
Filtering
You can now filter events by destination: GET /events?destination_id=des_456. This filters using the new matched_destination_ids field.
No data backfill
Existing events created before the upgrade will have an empty matched_destination_ids array. Only events published after the upgrade will have this field populated.
Action: Update any code that reads event.destination_id to use event.matched_destination_ids. If you need a single destination ID, use the first element of the array.
Delivery Metadata Timestamp Format
The timestamp field in delivery metadata has changed from Unix seconds to ISO 8601 format.
v0.15:
v0.16:
Action: Update any code that parses the timestamp metadata field to handle ISO 8601 (RFC 3339) format instead of Unix seconds.
Response Data Body Stored as Raw String
The response_data.body field in delivery attempts is now always stored as a raw string, regardless of the destination's response content type. Previously, JSON response bodies were parsed into objects.
API response change
v0.15 — JSON response body was a parsed object:
json
v0.16 — body is the raw response string:
json
Non-JSON responses are unchanged (already stored as strings).
Database migration
The attempts.response_data column is migrated from JSONB to TEXT (migration 000009). This migration runs automatically on startup. Any direct SQL queries that use JSON operators on response_data (e.g., response_data->'body'->>'key') will need to be updated.
Action: Update any code that reads response_data.body as a structured object. If you need the parsed object, parse the string with JSON.parse() (or equivalent) on the client side.
Alert Callbacks Replaced by Operator Events
The ALERT_CALLBACK_URL config has been removed. Alert notifications are now handled by the new operator events system, which supports multiple sink types and additional event topics.
Migration
If you were using ALERT_CALLBACK_URL to receive alert callbacks via HTTP, migrate to the operator events HTTP sink:
v0.15:
v0.16:
The HTTP sink signs payloads with HMAC-SHA256 and sends the signature in the X-Outpost-Signature header (format: v0=<hex>).
New sink options
In addition to HTTP, operator events can be sent to:
- AWS SQS —
OPERATOR_EVENTS_AWS_SQS_QUEUE_URL,OPERATOR_EVENTS_AWS_SQS_ACCESS_KEY_ID,OPERATOR_EVENTS_AWS_SQS_SECRET_ACCESS_KEY,OPERATOR_EVENTS_AWS_SQS_REGION - GCP Pub/Sub —
OPERATOR_EVENTS_GCP_PUBSUB_PROJECT_ID,OPERATOR_EVENTS_GCP_PUBSUB_TOPIC_ID,OPERATOR_EVENTS_GCP_PUBSUB_CREDENTIALS - RabbitMQ —
OPERATOR_EVENTS_RABBITMQ_SERVER_URL,OPERATOR_EVENTS_RABBITMQ_EXCHANGE
Event topics
Use OPERATOR_EVENTS_TOPICS=* for all topics, or specify a comma-separated list:
alert.destination.consecutive_failure— emitted at 50%, 70%, 90%, and 100% failure thresholdsalert.destination.disabled— emitted when a destination is auto-disabledalert.attempt.exhausted_retries— emitted when delivery exhausts all retry attemptstenant.subscription.updated— emitted on destination create/update/delete/disable/enable
Alert default changes
The alert thresholds have also changed:
| Setting | v0.15 Default | v0.16 Default |
|---|---|---|
| Consecutive failure count | 20 | 100 |
| Auto-disable destination | true | false |
If you relied on the previous defaults, set them explicitly:
Other Notable Changes
These changes are not breaking but may be useful to know about.
DELETE /destinations response
DELETE /tenants/{tid}/destinations/{did} now returns { "success": true } instead of the full destination object, matching the behavior of DELETE /tenants/{tid}.
Empty webhook header prefix
You can now disable the webhook header prefix by setting it to whitespace (e.g., DESTINATIONS_WEBHOOK_HEADER_PREFIX=" "). This results in headers like signature instead of x-outpost-signature.
Upgrade Checklist
-
Before upgrading:
- Decide whether to adopt
whsec_prefixed signing secrets or preserve previous format (setDESTINATIONS_WEBHOOK_SIGNING_SECRET_TEMPLATEif preserving) - Update code that reads
event.destination_idto useevent.matched_destination_ids - Update any timestamp metadata parsing from Unix seconds to ISO 8601
- Update code that reads
response_data.bodyas a parsed object — it is now a raw string - If using
ALERT_CALLBACK_URL, migrate toOPERATOR_EVENTS_*config - Review alert default changes (consecutive failure count: 20→100, auto-disable: true→false) and set explicitly if needed
- Update SDK dependencies to the latest version
- Decide whether to adopt
-
Upgrade:
- Update Outpost to v0.16 and restart — database migrations run automatically on startup
-
After upgrading:
- Verify event queries and filters work with
matched_destination_ids
- Verify event queries and filters work with