Skip to content

Case study · Field service operations

An event contract between the app and the CRM, so message copy never needs a deploy

Every customer text used to be hard-coded in the application. We split the system in two: the app emits a fixed catalog of business events, and the CRM owns every message, its timing and its opt-outs.

13
Business events in a frozen catalog
1
Outbound emitter for the whole app
500
Event keys held for de-duplication
0
Deploys needed to change a message

Context

A field-service app sends customers updates: enrolled, booking confirmed, technician on the way, job completed, leak detected. Operations wanted to change wording, timing and quiet hours themselves, and every change was a code release.

The problem

  • Message copy, retry rules and opt-out handling lived in application code, so marketing and operations depended on engineering for every edit.
  • Webhooks from the field-service platform are redelivered, and a faulty sensor can fire dozens of times a minute. Without protection, a customer could get the same text forty times.
  • A failed text must never block the thing that matters: an enrollment saved or a work order opened.

Architecture

  1. 01Events, not messagesThe app says what happened (job.on_my_way, leak.valve_closed). It never says what to text. Each event name is a contract: new ones may be added, existing ones are never repurposed.
  2. 02One emitterEvery outbound event goes through one module, which normalizes the phone number, attaches the payload and hands it to the CRM. There is exactly one place to look when a message did not go out.
  3. 03De-duplicate at the edgeThe last 500 event keys are remembered, so a redelivered webhook or a chattering sensor produces one message, not forty.
  4. 04Never block the business actionThe emitter cannot throw. If the CRM is slow or down, the enrollment still saves and the work order still opens; the event is logged for retry.

Security model

  • The CRM receives only the fields each event needs, not the full customer record.
  • CRM credentials are held server side; the browser never calls the CRM directly.
  • Opt-out and quiet-hour rules live in one place, the CRM, so compliance does not depend on every code path remembering them.

Tasks now automated

  • Sending the right customer update for each of 13 lifecycle events
  • Normalizing every phone number before it reaches the CRM
  • Suppressing duplicate events from webhook redelivery and faulty sensors
  • Enforcing quiet hours and opt-outs on every message

Time returned

Days to minutes
Turnaround on a copy change

Was a code change, review and release; now an edit in the CRM.

0
Engineering hours per message edit

Copy and timing moved out of the codebase entirely.

40 to 1
Texts from a chattering sensor

De-duplication collapses repeated events into one message.

Time figures are estimates per unit of work, based on the manual steps the build removed. Every other number on this page is measured.

Outcome

Operations edits message copy, timing and quiet hours in the CRM without an engineering ticket.

Duplicate texts from redelivered webhooks are blocked by design rather than by luck.

Draw the line where the people who change things work. Engineers own events; the business owns words.

Next step

Tell us which system is slowing you down.

A 15 to 20 minute scoping call. If it is a fit, scope, price and timeline follow in writing.