RideNow is a worked example that applies the full Specy three-layer discipline to a realistic Uber-like ride-hailing platform. The product is specified across three abstraction layers — a Product Requirements Document that names personas, jobs, features, and goals; a set of System Requirements in EARS that name testable obligations; and a Domain Model that names the entities, operations, events, invariants, agreements, and reactions the system realizes. The platform is decomposed into five bounded contexts — Rider Management, Driver Management, Ride Management, Geolocation & Routing, and Payment — each with its own ubiquitous language, its own systems, and its own slice of the three layers. A sixth requirement set (Platform NFR) covers the cross-cutting non-functional obligations that bind the whole platform.

The five bounded contexts

RideNow decomposes into five bounded contexts, each with a short identifier used as the requirement-ID prefix and in the domain DSL.

Context Shortname Responsibility
Rider Management (RDR) RDR Rider registration and phone verification, profile and saved addresses, payment-method references, ratings received, bans and appeals — including a permanentlyBanned final state and the cross-context bridge that records driver-given ratings on RideCompleted.
Driver Management (DRV) DRV Driver onboarding, identity and document verification, vehicle registration with inspection eligibility, availability state, ratings received, suspension with appeal path.
Ride Management (RIDE) RIDE Ride lifecycle from request to completion — upfront fare display, driver matching with offer rotation, pickup-to-completion tracking, cancellation policy with rider/driver penalties, and safety tooling (emergency events, trip sharing, post-ride reports).
Geolocation & Routing (GEO) GEO Real-time driver positioning, proximity queries ordered by ETA to pickup, ETA computation with periodic destination-ETA refresh, ETA variance alerts, dynamic route recalculation, surge-zone detection with a 5.0x multiplier cap and surge-frozen-at-confirmation guarantee.
Payment (PAY) PAY Payment-method validation, fare calculation, pre-authorization and capture, refunds (system-cancel, driver-fault), driver weekly payout and on-demand instant payout, receipts.
Shared Kernel (Shared) Shared Cross-cutting value types co-owned by every context: Amount (money + currency), Currency (ISO 4217 reference data — code, numeric code, fraction digits — modeled on java.util.Currency), Distance (meters), Duration (seconds), and the Currencies enum of ISO 4217 codes. Single source of truth for these unit-bearing types — replaces the prior per-context Money and the duplicated local Distance / Duration declarations.

Each context has its own three pages in the nav: a PRD (who it serves, what problem it solves, what features it offers), a System Requirements page (testable EARS obligations including a per-context Non-Functional set), and a Domain Model page (entities, value types, commands, events, invariants, services, reactions — every element rendered as its own per-element narrative subsection alongside the verbatim .domain DSL).

Totals across the example: ~161 context-scoped EARS requirements plus an organization-level Platform NFR set of 18 — ~179 system requirements in total. The breakdown:

Set Reqs Must Should Could
Rider Management 22 13 9 0
Driver Management 32 28 4 0
Ride Management 48 40 5 3 (scheduled rides)
Geolocation & Routing 19 16 3 0
Payment 40 34 3 3 (instant payout)
Platform NFR (organization) 18 18 0 0
Total 179 149 24 6

Cross-context dependencies

The five contexts do not live in isolation — a ride produced by Ride Management needs Geolocation to find a nearby driver, Payment to capture the fare, Driver Management to confirm the matched driver is verified and online, and Rider Management to confirm the requester is ready-to-ride. These are asynchronous collaborations across context boundaries, expressed at runtime as events and commands crossing the line, and at the model level as context-map patterns.

Requirement Depends on Nature of the dependency
REQ-RIDE-002 (Ready-to-ride gate) Rider Management Ride ← Rider: gate check on rider status before request
REQ-RIDE-003 (Upfront fare display) Payment Ride → Payment: compute fare estimate (with surge if any)
REQ-RIDE-020 (Nearby driver query) Geolocation Ride → Geo: proximity query ordered by ETA to pickup
REQ-RIDE-045 (Tracking during trip) Geolocation Ride → Geo: consume live location stream and refreshed ETA
REQ-RIDE-048 / REQ-RIDE-049 (Fare finalization & capture) Payment Ride → Payment: compute final fare and capture authorized amount
REQ-RIDE-060 (Cancel before assignment) Payment Ride → Payment: release pre-auth on system / pre-assignment cancel
REQ-RIDE-064 / 066 (Driver penalties) Driver Management Ride → Driver: trigger suspension on excessive cancels or no-shows
REQ-RDR-006 (Saved payment method) Payment Rider → Payment: validate method reference on save
REQ-DRV-032 (Match-eligibility) Ride / Geo Driver → Ride/Geo: publish availability so matching can see it
REQ-GEO-003 (Stale position ineligibility) Driver Management Geo → Driver: notify on ineligibility (DriverPositionStale)
REQ-GEO-013 / 014 / 015 (ETA refresh, variance, recalc) Ride Management Geo → Ride: in-flight ETA + route updates
REQ-GEO-023 (Surge visible at fare estimate) Ride / Payment Geo → Ride → Payment: surface multiplier before commit
REQ-GEO-024 (Surge frozen at confirmation) Ride Management Geo ↔ Ride: do not apply surge after the fare is committed
REQ-PAY-020 (Pre-authorization) Ride Management Payment ← Ride: hold funds at request time
REQ-PAY-040 (Driver earnings) Ride Management Payment ← Ride: credit balance on ride completion
REQ-PAY-060 (Auto refund on system cancel) Ride Management Payment ← Ride: refund on system-driven cancellation
REQ-PAY-064 (Driver-fault refund) Driver Management Payment → Driver: deduct from driver balance

These pairs are good places to look at the Domain Model pages for each context — the context-map pattern (Open Host Service, Anti-Corruption Layer, Customer/Supplier, Published Language) is declared on the consuming side, and the published events are listed under each Domain page’s External-bound events section.

How to read this example

Two reading paths work, depending on what you want to learn:

  • Follow a context end-to-end. Pick one context (Payment is the most intricate; Geolocation & Routing is the most query-heavy and the easiest to skim) and read its three pages in order: PRD → System Requirements → Domain Model. You’ll see the same concepts — Payment, FareBreakdown, Capture, SurgeMultiplier, RideRequest — surfaced with different grain at each layer, using the same vocabulary at every step.
  • Follow a layer across contexts. Pick one layer (the PRD group is the most approachable) and read across all five contexts. You’ll see how bounded contexts carve the product into manageable pieces without breaking the ubiquitous language.

For a first pass, the best sequence is: this overview → one PRD → the matching SysReq → the matching Domain Model. Start with Rider Management if you want the simplest context (single aggregate root with a clean lifecycle); start with Geolocation & Routing if you want the smallest domain with the clearest cross-context surface; start with Payment if you want the deepest model.

What this example illustrates

  • scoped-to discipline. Every system requirement is scoped-to exactly one bounded context. A single product feature — e.g., “Free cancellation before driver assignment” — typically produces multiple requirements, one per context involved. See how REQ-RIDE-060 (ride cancellation) and REQ-PAY-060 (system-cancel refund) realize one PRD feature across two contexts, with the Payment side reacting to events emitted by the Ride side.
  • satisfies traceability. Every domain element that realizes a requirement declares satisfies [REQ-…]. Coverage queries traverse these lists; orphans (empty satisfies) are flagged for review. Each Domain page closes with a Traceability Matrix table mapping every requirement in scope to the elements that realize it.
  • Ubiquitous language sharing. The same noun means the same thing across all three layers within a context. RideRequest appears in the Ride Management PRD (as a user-visible action), in the SysReq (as the subject of the obligation), and in the Domain Model (as an entity with a state machine). No translation table is needed to follow a concept across layers. When a noun must mean different things in different contexts (e.g., driver in Driver Management’s verification lifecycle vs. driver in Ride Management’s offer/dispatch flow), the metamodel forces an explicit cross-context translation.
  • Context-map patterns in practice. Ride Management consumes nearby-driver queries from Geolocation through an Open Host Service. Geolocation publishes SurgeActivated / SurgeDeactivated / ETAVarianceDetected to Ride Management as a Published Language. Driver Management consumes DriverPositionStale from Geolocation through an Anti-Corruption Layer that translates it into a local GoOffline(reason=stalePosition) command. Payment cross-credits/debits Driver Management balances on capture and refund. Each pattern is visible on the Context Map table at the top of each Domain page.
  • Verifiable properties. Every aggregate carries invariants (with explicit enforcement: rejection, compensation, or alert). Every operation carries preconditions and postconditions. Every state machine carries transition guards and state-scoped invariants. Cross-aggregate truths use agreements maintained by reconciliations with bounded inconsistency windows. Together they define the property-based test surface — the obligations a generator can drive into the system to falsify. This is the built-in verifiability the Specy domain metamodel guarantees.
  • Temporal events and reactions. Several lifecycle behaviors are driven by temporal events (e.g., RideOfferDeadlineElapsed, weekly payout cutoffs) and reactions that fire on internal or external events. Reactions name the cross-context behavior explicitly rather than hiding it in implementation code.

Pick a context from the nav on the left to begin.