Events and the outbox
By Marek Nowak · created 17 May 2021, 13:00 UTC · last updated 4 Aug 2026, 09:25 UTC · version 9
eventsoutboxidentity-servicenotifier
identity-service tells the rest of the world about changes through events. It never calls another service in the middle of a transaction. Why: ADR-004.
How it works
- A change and its event are written in the same database transaction. The event goes into
outbox_events(event_id,client_id,type,payload,attempts,next_attempt_at,delivered_at,last_error). DeliverOutboxEvents(php artisan events:deliver) runs every minute, takes the waiting rows oldest first and posts each one to notifier'sPOST /events, signed with an HMAC of the body (X-Acme-Signature: t=...,v1=...). It setsdelivered_at; a failed post is tried again after 1, 2, 4, 8 … minutes, at most an hour apart, ten times in all.- Delivery is at least once, so notifier ignores an event id it has already handled.
- Once notifier has a phone code, the code is blanked in the row; delivered rows stay in the table.
If delivery stops, nothing is lost: events pile up in outbox_events and go out when it restarts. The outbox lag alarm fires when the oldest undelivered row is older than five minutes (Monitoring and alerts).
Events
| Type | Sent when | Payload (besides ids) |
|---|---|---|
RequestSubmitted | someone asks for access | the request (depot, items or bundle, reason), the person, who it waits on, the client's administrators |
RequestDecided | an approver or an administrator approves or declines | the decision, the note, who decided, the person who asked |
ReminderDue | the hourly reminder job finds a request waiting 24 hours, then each day after | the request, how long it has waited, who it waits on |
DepotSsoEnabled | a depot's single sign-on is switched on | the depot, who switched it, its people and manager |
PhoneCodeRequested | a depot worker asks for a sign-in code | the phone number, the code and when it expires |
Closing a request after 14 days writes no event: nobody is told when a request expires. That is a product decision waiting to be made, not a bug in the outbox.
Rules
- Payloads carry each person to tell with their name, email, phone and language, so notifier words and sends a notice from the event alone and never calls identity-service back.
- Never post to notifier from application code. Write to the outbox.
- A new event type needs a row in the table above and a consumer, or a line saying why it has none.
Change history
| Version | Date | Who | What |
|---|---|---|---|
| 7 | 2 Jun 2025 | Marek | access_request.expired |
| 8 | 22 Jul 2026 | Noor, Marek | Reminder events |
| 9 | 4 Aug 2026 | Elif | In-app notices read the same events |