Contact
Home / Insights / Engineering operations

Engineering operations

A notification was sent. Does the user know what happened?

A service can accept a message without proving that a person saw it. Notifications are an important part of the experience, but the product still needs an authoritative place to show what happened.

For teams connecting important product events to messages users can act on.

The useful starting point

Keep the business event, message delivery and user-visible state distinct. A notification should help someone understand the product, not become its only record of an important event.

Name the event before choosing a channel

Start with what changed in the product and who needs to know. A completed payment, a ride update and a request needing attention have different purposes. The event should be understandable before it is turned into a push notification, email or another message.

Then define the information and action the message should provide. This keeps the channel implementation connected to the task instead of producing a collection of disconnected alerts.

Trace the product event and the message separately

Illustrative example · a simplified payment-notification example, not a client incident

Two related histories with different meanings
ObservationProduct recordNotification recordWhat a user or operator should be able to establish
A payment is confirmedThe agreed completion state is recordedA message is requestedThe underlying transaction exists independently of delivery
A provider accepts the message requestPayment state is unchangedAccepted by the messaging providerAcceptance is evidence about dispatch, not proof of reading
Delivery fails or remains unresolvedPayment state is unchangedFailure or uncertainty is visibleThe team can investigate the attempt and the app can still show the transaction
A retry is attemptedThe payment is not repeatedAnother delivery attempt is related to the same eventCommunication retry and business action remain distinct
The user opens the appThe current transaction is availableAny observed message interaction is recorded separatelyThe product provides an authoritative route to the information

The table is useful because it exposes a boundary: retrying communication must not inadvertently repeat the underlying action. It also makes clear which state a person is actually looking at when investigating a complaint.

Agree what the delivery labels mean

A message’s lifecycle is separate from the business event
  1. 1Message requested
  2. 2Dispatch accepted or rejected
  3. 3Delivery information received if available
  4. 4User interaction observed if the product records it

A delivery label should describe an observation the system can support. “Sent”, “delivered” and “read” are not interchangeable. The exact reporting available depends on the channel and provider.

Keep the event reference, message identity and attempt history connected. Those references help someone explain whether a problem concerns the business event, the request to communicate it or a later delivery stage.

Decide whether a late message still helps

A status update can become misleading after the product has moved on. Define which messages remain useful, what should expire and where the person should check the current state.

A message can also be important enough to need another route to the information. That is a product decision to make explicitly. The shared notification service can support communication responsibilities, while the application remains responsible for explaining the current product state.

Centralise the responsibilities that are shared

When several services need to send messages, shared handling can give templates, routing, delivery attempts and logs an explicit home. That is one part of Codek’s payments engineering work: a dedicated notification service rather than separate dispatch implementations across the product.

A shared service still needs a clear boundary. The originating service should know what event occurred; the notification layer needs the information required to communicate it. Avoid making the template itself the only definition of the business event.

Do not confuse accepted with seen

Record delivery stages with names that reflect what is actually known. Sending a request to a provider, having it accepted and having a message reach a device are different observations. Evidence that a person read a message may be different again.

Firebase’s message-delivery documentation (opens in a new tab) illustrates why delivery reporting needs careful interpretation. The application should not promise more than its evidence supports.

Make retries useful rather than confusing

Decide when a message should be retried, when it is no longer relevant and how repeated requests are identified. An old status message arriving after a newer one can confuse a person even if both messages were technically delivered.

  • Which product event triggered the message?
  • Is repeated delivery handled intentionally?
  • Can a late message become misleading?
  • Where can the person check the current state?
  • Can the team trace a failed delivery attempt?

Shared dispatch in our payments work

Our payments work includes a shared notification-dispatch service with templating, channel routing, retry handling and logging. Our mobility work also includes a separate notification service.

Giving dispatch an explicit responsibility makes it easier to discuss where message changes and delivery investigation belong. The event still originates in the product: a shared template or delivery attempt should not become the only record of what happened.

The payments case gives the broader context. The worked timeline in this guide explains the boundary between business state and communication; it does not reproduce a client event or promise a particular delivery rate.

Common questions

Does provider acceptance prove that a person saw a notification?

No. It establishes a particular stage in dispatch. The channel’s delivery information and any observation of user interaction need to be interpreted separately.

Should we retry every failed notification?

Define relevance, expiry and repeat handling for the event and channel. A late or duplicated message can confuse a user, so a retry policy needs to consider the current product state.

Keep exploring

All insights

Payments engineering

Payment webhooks: knowing what happened after a timeout

A request can time out while a payment continues elsewhere. A provider can send the same update twice. The engineering problem is keeping a clear account of the transaction while different systems report what they know.

5 min read

Mobility engineering

Live driver tracking: when locations stop updating

A map can keep showing a driver’s last position after updates stop. The important question is whether the product knows how recent that position is and what the passenger should understand from it.

5 min read