fivenines
4/38
Lesson 1.2 99.9%

Identity and onboarding

🎯 Objectives
  • Design rider signup and the multi-step, vendor-dependent driver onboarding pipeline.
  • Explain why onboarding is modeled as a resumable state machine rather than a single transaction.
🔗 Connect

From 1.1: the Identity service owns users, credentials, sessions, and devices. From 0.2: background checks are bought, not built — which means onboarding contains a step we don't control.

Rider signup is deliberately boring: phone number + OTP, a JWT session token validated at the gateway (so downstream services never re-authenticate), and a device record for push notifications. Boring is the goal — authentication sits on the critical path of every request, so it must be the most cache-friendly, least clever component we own.

Driver onboarding is the interesting half. It spans days, involves document upload, human review, and a third-party background check whose latency we cannot control. Any process with external waits must be a resumable state machine persisted in the database — never an in-memory workflow that dies with a deploy. This is the first appearance of a pattern that recurs in trips (1.7) and payments (1.8): long-running work = explicit persisted states + events that move between them.

stateDiagram-v2
    [*] --> Applied : driver submits form
    Applied --> DocsPending : account created
    DocsPending --> DocsReview : license, insurance, vehicle photos uploaded
    DocsReview --> DocsPending : rejected — resubmit
    DocsReview --> BackgroundCheck : docs approved
    BackgroundCheck --> ManualReview : vendor flags record
    BackgroundCheck --> Approved : vendor clears
    ManualReview --> Approved : ops approves
    ManualReview --> Denied : ops denies
    Approved --> Active : training completed, first go-online
    Denied --> [*]
Driver onboarding as a persisted state machine. Every transition is an auditable event — regulators will ask (1.13).

Worked example: the background-check step

sequenceDiagram
    autonumber
    participant D as Driver app
    participant ID as Identity service
    participant S3 as Object store
    participant V as Check vendor
    participant OPS as Ops console
    D->>ID: upload documents
    ID->>S3: store encrypted docs
    ID->>ID: state = DocsReview
    OPS->>ID: approve docs
    ID->>V: request background check (async, webhook callback)
    ID->>ID: state = BackgroundCheck
    Note over ID,V: hours to days pass — state survives deploys and restarts
    V-->>ID: webhook: clear
    ID->>ID: verify webhook signature, state = Approved
    ID->>D: push notification: you're approved
The vendor call is asynchronous with a signed webhook callback — never a blocking HTTP wait measured in days.
⚠️ Pitfall

Webhooks arrive late, duplicated, and out of order. The handler must be idempotent (a duplicate "clear" is a no-op) and must validate state transitions (a "clear" arriving after ops already denied the driver must not resurrect the application). Idempotency gets a full treatment in 2.4 — here you just meet it.

Next step

See what actually stuck.

Take the practice scenarios now.