Goal
Use S2 as an observable application service instead of an opaque file container.Prerequisites
- An existing S2 bucket
- A StackShift API token
Workflow
1
Create a managed event subscription for the object events and key patterns the application needs.
2
Pull pending deliveries, process them idempotently, and acknowledge success or request a retry.
3
Use access logs and analytics to investigate traffic, errors, bandwidth, and busy prefixes.
4
Create CSV or JSONL inventory exports when a workload needs a full object manifest.
5
Enable website settings and verify a custom domain when the bucket should serve static content.
Event delivery release status
Signed push delivery and fenced pull acknowledgements are implemented locally and unreleased. They require migration 000523, the matching API/dashboard, and the Object Store platform worker. Deployment and production HTTPS acceptance remain pending; do not assume an older deployment exposes these additions. Existing subscriptions retain pull mode.Pull claims and interruption recovery
Pull /api/v1/buckets/{bucketID}/event-subscriptions/{subscriptionID}/deliveries. Each delivery includes claim_id. Process idempotently using event_id and POST {“claim_id”:“the returned value”,“retry”:false} to /api/v1/buckets/{bucketID}/event-deliveries/{deliveryID}/ack. Use retry:true after a recoverable processing failure. Claims expire after 15 minutes. A stale or expired claim returns 409 and cannot acknowledge a newer consumer’s lease. Legacy requests without claim_id work only for a first, unexpired claim; retried or reclaimed deliveries require claim_id. Pull again after expiry and use the new claim. Acknowledge only after durable processing or enqueueing.Create a signed HTTPS subscription
Create through the existing event-subscriptions endpoint with delivery_mode:“push”, a public HTTPS url, event_types, and optional literal prefix/suffix filters. Private/reserved destinations, HTTP, credentials in URLs and unsafe redirects are rejected by the shared webhook transport. The signing secret is returned once; keep it in your application’s secret store. The signed JSON body contains id (stable event ID), type and data. X-StackShift-Delivery-ID identifies this subscription’s delivery. Verify X-StackShift-Signature against the exact raw request body before parsing it. HMAC-SHA256 signs the ASCII timestamp, a dot, and the raw body. Enforce a timestamp tolerance and deduplicate on the signed event ID.Verify the raw Node.js request body
Durable, idempotent consumption
After verifying the signature, persist the signed event ID and payload in your application database with a unique constraint. Return 2xx only after the insert commits. A duplicate event ID is already accepted and can return 2xx. Have your application worker apply business changes and mark the inbox row processed in one transaction, or propagate the same idempotency key to an external service. A process-local Set is not durable deduplication.PostgreSQL inbox
Pause, rotate, inspect and replay
- PATCH /event-subscriptions/{subscriptionID} with enabled:false pauses new claims; enabled:true resumes them. Already in-flight requests may finish.
- DELETE /event-subscriptions/{subscriptionID} removes the subscription, pending deliveries and delivery history. The dashboard asks for confirmation and clears the deleted subscription from its recovery view. Objects remain available; already in-flight requests may finish.
- PATCH the same URL with rotate_secret:true returns a replacement secret once. Update the receiver immediately; an in-flight request may still be signed with the old secret. Retain the previous receiver-side secret briefly if accepting those requests is intended.
- GET /event-subscriptions/{subscriptionID}/history returns up to 50 deliveries with attempts, result codes and failures. Pass the returned next_cursor as before for older results.
- Failures retry with exponential backoff, starting at 30 seconds and capped at one hour. The tenth failed attempt exhausts automatic delivery. Network timeouts may mean the receiver already accepted an event; delivery is at least once.
- POST /event-deliveries/{deliveryID}/replay explicitly requeues a delivered or exhausted push delivery on an enabled subscription. Repeated clicks while it is pending do not enqueue duplicates. The stable event ID remains unchanged. Attempt history is retained and a failed replay after exhaustion requires another explicit replay.
- Request bodies are bounded by the stored event payload, responses are retained up to 2 KiB, and each outbound request has a 10-second timeout. Never treat an HTTP response as proof that downstream business processing completed.
Managed object events
- Event types are
object.created,object.overwritten, andobject.deleted. - Subscriptions can filter by object-key prefix and suffix.
- S2 stores deliveries in a managed queue; clients pull batches and acknowledge each delivery.
- Acknowledgement can mark processing complete or request another attempt after a recoverable failure.
- Pull and acknowledgement operations remain tenant- and bucket-authorized through the StackShift control plane.
Analytics and access logs
Bucket analytics report stored bytes, object count, request count, errors, bandwidth, and the most active prefixes. The default analytics window is the previous 30 days, or you can provide an RFC 3339 start time. Access logs record the operation, object key, status, bytes in and out, request identifier, access key when available, and occurrence time. Use them to distinguish authentication, quota, application, and service failures.Inventory exports and catalogs
Inventory exports produce CSV or JSONL manifests and can be limited to one prefix. Each export has a durable status, row count, and authenticated download operation. Catalogs expose object metadata through an Iceberg-compatible metadata document. The bounded query API supports selected columns from the object inventory with an optional key-prefix filter and a limit up to 1,000 rows.Static websites and custom domains
Website mode serves the configured index object for root and directory requests and can use a configured error object for missing content. Configure cache-control headers on uploaded objects to control browser and intermediary caching. Custom domains use the StackShift domain-verification flow. After verification, attach the active domain through bucket settings and keep DNS aligned with the target returned by StackShift.Expected result
Object changes can drive durable application work, operators can explain storage activity, and static buckets can be published intentionally.
Common failures
Related guides
S3 operations and presigned access
Use the supported S3 operations, conditional requests, object metadata, tags, multipart uploads, and presigned URLs.
Versioning, lifecycle, and retention
Protect object history, restore earlier versions, automate aging policies, and prevent protected objects from being deleted too early.
Capacity, monitoring, and recovery
Monitor bucket usage, handle temporary service responses, protect critical objects, and validate application recovery.