Postal Service
1. Summary
The Postal Service is a message routing microservice that ensures platform-generated messages are delivered to the appropriate client application (platform tenant). It does not modify, parse, or template messages. Instead, it forwards them exactly as received via HTTP POST to the client’s registered endpoint.
This approach minimizes integration friction while enabling observability, fairness, and operational consistency at scale.
2. Why This Matters
Many delivery mechanisms today rely on implied behavior, like silent retries or default timeouts, that can lead to missed messages, confusing logs, or inconsistent client experience.
We’re aiming to solve that by building a system where:
- Delivery decisions are based on clear conditions (like time and registration status),
- Failures are surfaced immediately and handled explicitly,
- Retry logic is controlled and predictable,
- Clients always know what to expect.
This reduces confusion, accelerates onboarding, and simplifies support.
3. Key Characteristics
- Structured delivery flow: Messages are evaluated and sent based on clear metadata (e.g. which client they belong to and when they should be delivered).
- Safe retry behavior: The system retries failed deliveries with exponential backoff, avoiding overwhelming clients or silently repeating indefinitely.
- Clarity over cleverness: We avoid guesswork and defaults. Everything, including registration, retry timing, and routing, is explicitly defined.
- Time-aware without being time-fragile: The system expects a consistent sense of time (e.g. NTP-synced infrastructure) and uses delayed Service Bus enqueue for precise retry scheduling.
4. System Components
5. What Client-Applications Need to Do
These requirements are introduced during the onboarding of each client-application to the platform. The goal is to keep integration simple, predictable, and consistent across teams.
Client-applications don’t need to manage queues, inspect message internals, or participate in custom workflows. Instead, they interact with the platform through a narrow, well-defined delivery contract:
- Register once using a unique client-application name and HTTP delivery endpoint. Registration is handled through the Registration Service as part of the client-application onboarding process.
- Receive messages via standard HTTP. Each client-application exposes a lightweight HTTP endpoint that accepts JSON payloads with delivery metadata.
- Return appropriate status codes:
2xxsignals successful handling. This is the only accepted success range.
6. Delivery Mechanism and Message Format
Postal delivers messages via HTTP POST to the client’s registered endpoint.
Message Payload
Each message has the following shape:
clientApplicationId: identifies the target client application.body: arbitrary JSON payload. Postal does not inspect or transform this value; it is forwarded exactly as received.
6a. Client Responsibilities
Client applications must:
- Register with a unique name and HTTP delivery endpoint via the Registration Service.
- Expose an HTTP endpoint that accepts JSON payloads.
- Return
2xxto confirm successful delivery. - Handle retries idempotently to avoid duplicate processing.
- Monitor for messages and problem topic entries.
7. Developer Integration Checklist
To integrate with Postal:
- Register your client-application name and HTTP endpoint with the Registration Service.
- Expose a valid HTTP endpoint that accepts the message payload format above.
- Ensure your endpoint returns a
2xxstatus code on success. - Implement idempotent handling of messages.
- Monitor retry activity and the problem topic for delivery failures.
8. Authentication
Inbound (requests to Postal)
Incoming HTTP requests are validated using Azure AD JWT tokens. The service validates tokens against the Azure AD JWKS endpoint using the configured tenant and client ID.
Outbound (Postal calling the Registration Service and client endpoints)
Postal authenticates outbound service-to-service calls using Azure Managed Identity, acquiring tokens scoped to the configured App ID URI.
9. Retry Behavior
When HTTP delivery fails, Postal schedules a retry using Azure Service Bus delayed enqueue (scheduledEnqueueTimeUtc). Backoff is exponential, capped at 60 seconds:
Retries also support a ramp-up direction: if delivery begins recovering, the retry interval halves on each success, converging back to zero.
Each topic subscription has a MaxDeliveryCount of 3. If a message fails that many consecutive attempts at the Service Bus level, it is automatically moved to the subscription’s dead-letter queue as a safety backstop.
10. Problem Topic
When a delivery failure is permanent (e.g. the client application is not registered), Postal publishes a problem event to the Problem Topic instead of retrying. Problem events follow the RFC 7807 format:
A 404 response from the Registration Service is treated as a permanent failure. All other errors trigger the retry flow.