🏛️ Driveway Platform — Services Architecture
What is this? A plain-English map of every backend service in the Driveway ecosystem: what each one does, what it owns, and how they all sync with each other, with the Admin API, and with Salesforce.
Informative overview only — no infrastructure identifiers, credentials, URLs, or vault names. Flows are described by role.
#1. The 60-Second Mental Model
Driveway is a distributed, event-driven platform written mostly in Kotlin + Spring Boot, with a Next.js web app on top. Three ideas explain almost everything:
- Each service owns one domain — inventory, cart, pricing, incentives, taxes, valuation, accounts, etc. They never reach into each other's databases.
- Admin API is the configuration hub — dealerships, zones, and regional rules live there; everyone reads from it.
- Salesforce is the system of record for the deal — once an order is placed, Salesforce drives the milestones and broadcasts them back as events.
#2. The Services, One by One
#🛒 Shop & Buy
Odyssey API — Inventory & Search
- Owns: the live vehicle catalog, full-text search (Atlas Search), leasing data, vehicle availability, 360° spin metadata, and search-ranking score weights.
- Stack: Kotlin + Spring Boot, Netflix DGS GraphQL, MongoDB. Five deployable modules (
routes,search,cron,consumer,availability). - How it gets data: a cron import reads vehicle files (EDS) every 30 minutes, writes them to the catalog, then publishes inventory deltas to a service-bus topic for downstream consumers.
- Syncs with Admin API: reads dealership + zone data to enrich each vehicle (location, free-shipping zones).
- Syncs with Salesforce: none directly — it's purely the catalog/search brain.
Cart Service — Cart & Order Lifecycle
- Owns: shopping carts, order records, the 15-stage order progress (the tracker), delivery status, and vehicle locking (
purchasePending). - Stack: Kotlin + Spring Boot, REST + Netflix DGS GraphQL, MongoDB.
- Reads from: Odyssey (availability), Incentives (rebates), Taxes & Fees (tax/shipping), Products (F&I), Valuation (trade-in), Admin (shipping zones).
- Syncs with Salesforce: inbound — receives order milestones (see §3). outbound — publishes shopping intents.
- Serves the tracker: the order progress bar is served by REST (
/orders); GraphQL (getCurrentCart) serves the commerce view (cost, vehicle, trade-ins).
Offer API — Vehicle Offers & Pricing
- Owns: vehicle offers, pricing strategy, and dealership/region markup rules. A consolidation of several legacy pricing services into one.
- Stack: Kotlin, MongoDB.
- Called by: Cart (offer pricing), Odyssey (search/detail pricing). No Salesforce sync.
#💵 Money & Products
Incentives API — Rebates & Leasing Programs
- Owns: OEM incentive/rebate data and leasing programs (sourced from a third-party incentive service).
- Stack: Kotlin + Spring Boot, Postgres.
- Sync: consumes Odyssey's inventory-delta topic (to fetch incentives for new vehicles) and publishes a leasing/incentives topic that Odyssey consumes back. Cart reads incentive pricing on demand.
Taxes & Fees API — Tax, Fee & Shipping Estimation
- Owns: tax estimates (state/county/city), state-to-state shipping cost matrix, and transaction processing via a third-party tax vendor.
- Stack: Kotlin + Spring Boot.
- Called by: Cart, Prequalification, Backpack. Pushes finalized deals to the tax vendor after proposal acceptance.
Products API — Finance & Insurance (F&I) Products
- Owns: the F&I catalog (oil & filter, valet, tire & wheel, vehicle service contract, loss protection) and rate caching.
- Stack: Kotlin + Spring Boot, MongoDB.
- Sync: consumes the inventory-delta topic to pre-fetch provider rates; Cart pulls product pricing on demand. No Salesforce sync.
Prequalification API — Loan Prequalification
- Owns: global and vehicle-specific loan prequalification applications and their association to users.
- Stack: Kotlin + Spring Boot, MongoDB.
- Reads from: Admin (dealership), Vehicle Service (specs), Incentives, Taxes & Fees, Cart, plus external credit/eligibility providers.
- Syncs with Salesforce: outbound — publishes finance intents to the intents topic, which the Ecommerce Intent Service forwards to Salesforce.
Valuation API — Trade-In Valuation
- Owns: trade-in valuations and vehicle detail lookups (from third-party valuation/CarFax-style sources). Consolidates several legacy lookup services.
- Stack: Kotlin + Spring Boot, Postgres.
- Called by: Cart, Backpack, Prequalification. No Salesforce sync.
#🔄 Sell & Trade
Backpack — Sell-Flow Backend
- Owns: the customer sell/trade-in flow — appraisals, inspection appointments, and trade-in offers.
- Stack: Kotlin + Spring Boot, MongoDB; integrates an appointment-booking vendor.
- Reads from: Vehicle Service, Valuation, Admin, Incentives.
- Syncs with Salesforce: not yet — SELL-case integration is pending (this is why the order tracker currently skips SELL events).
#⚙️ Platform & Identity
Admin API — Configuration Hub
- Owns: the master dealership records, zones, fulfillment/free-shipping rules, and user roles.
- Stack: Kotlin + Spring Boot.
- Role: read-heavy hub. Odyssey, Cart, Prequalification, Backpack, and Vehicle Service all read dealership/zone config from it. Dealership/account data originates in Salesforce and flows into Admin API (Salesforce → Admin, one way).
Account Center API — User Data & Preferences
- Owns: user accounts (identity via Auth0), saved searches, favorites, "my vehicles," addresses, email validation, and GDPR deletion.
- Stack: Kotlin + Spring Boot, Postgres + Auth0. No direct Salesforce sync.
Vehicle Service — Vehicle Specs
- Owns: vehicle specification data (year/make/model/trim, drivetrain, fuel, etc.) — specs, not inventory.
- Stack: Kotlin + Spring Boot, Postgres; data arrives via a managed data-pipeline from the EDS source.
- Called by: Backpack, Prequalification. No Salesforce sync.
#☁️ Salesforce + the Bridge
Salesforce (FreewayCRM) — System of Record for the Deal
- Owns: the Case/Deal/Vehicle/Account/Intent objects, and the Order Tracker Event platform event.
- Stack: Salesforce Apex + Flows + Lightning.
- Publishes: order milestones as platform events whenever a Case or Vehicle status changes (via Apex triggers).
Salesforce Integration API — Event Consumer & Bridge
- Owns: the always-on consumer that subscribes to Salesforce's order events, de-duplicates them, and forwards them to Cart.
- Stack: Kotlin + Spring Boot (coroutines), MongoDB (event store for idempotency).
- Direction: Salesforce → (this bridge) → Cart. SELL cases are skipped until Backpack integration lands.
Ecommerce Intent Service — Intent Submission
- Owns: reliable submission of finance/shopping intents into Salesforce, with an audit log and retry/dead-letter handling.
- Stack: Kotlin + Spring Boot, MongoDB.
- Direction: Prequalification / Cart → intents topic → (this service) → Salesforce.
#3. How Everything Syncs with Admin API & Salesforce
#Admin API — the read-only config hub
Dealership and account data originates in Salesforce and is synced into Admin API. Every other service then reads config from Admin API — nobody writes back. This keeps one source of truth and avoids duplicated dealership data across services.
#Salesforce — two opposite flows
There are two distinct directions of Salesforce sync, and it helps to keep them separate.
Flow A — Order milestones (Salesforce → Cart). This is the order tracker.
Flow B — Intents (Backend → Salesforce). This is how a customer's finance/shopping interest becomes a Salesforce lead.
🔑 The mental shortcut: Milestones flow out of Salesforce to the customer's tracker. Intents flow into Salesforce from the shopping/finance services.
#4. The Sync Mechanisms (cheat sheet)
| Mechanism | Used for | Example |
|---|---|---|
| REST | service-to-service reads | Cart → Taxes & Fees for an estimate |
| GraphQL | rich client reads | Web app → Cart getCurrentCart; Web → Odyssey search |
| Service Bus topics | async fan-out between services | Odyssey publishes inventory deltas → Incentives, Products consume |
| Salesforce Pub/Sub | order milestones out of Salesforce | Order events → Salesforce Integration API |
| Intents topic | intents into Salesforce | Prequalification → Ecommerce Intent Service → Salesforce |
| Data pipeline / cron import | bulk external data | EDS vehicle files → Odyssey; specs → Vehicle Service |
#5. End-to-End: One Order's Journey
- Order placed — Cart creates the order and marks the vehicle
purchasePending(Odyssey honors the lock). - Intent published — Cart emits a shopping intent on the intents topic.
- Into Salesforce — the Ecommerce Intent Service submits it; a Case is created.
- Deal processing — the deals team advances the Case through its stages. 5–7. Milestones flow back — each status change becomes an order event, the bridge forwards it, and Cart records the timestamp (back-filling earlier steps so the bar never shows gaps). 8–9. Customer sees progress — the web/mobile tracker renders the stages; on delivery the order is marked COMPLETED.
#6. Technology At A Glance
| Layer | Technology |
|---|---|
| Language | Kotlin (JDK 21), TypeScript |
| Backend framework | Spring Boot 3.x (WebFlux, reactive) |
| Web | Next.js (App Router) |
| Databases | MongoDB (catalog, carts, orders), Postgres (config, users) |
| Search | MongoDB Atlas Search |
| APIs | REST + GraphQL (Netflix DGS) |
| Messaging | Service Bus topics (async fan-out) |
| Event streaming | Salesforce Pub/Sub (Avro) |
| Identity | Auth0 (customers), Salesforce (CRM) |
| Observability | Datadog APM + metrics |
#7. Design Principles That Tie It Together
- One domain per service — no shared databases; integration only through APIs and topics.
- Admin API as the single config hub — dealership/zone data read everywhere, written nowhere else.
- Event-driven order tracking — Salesforce is the source of truth; milestones fan out asynchronously so a slow consumer never blocks the deal.
- Async intent submission — publishing intents to a topic (instead of calling Salesforce inline) means a Salesforce hiccup can't fail the customer's checkout.
- Idempotent + replayable — the order-event bridge de-dupes and bookmarks its position, so restarts never lose or double-count milestones.
- Back-fill for a clean UX — Cart fills in any missing earlier stages at delivery so the progress bar always reads top-to-bottom.
#8. ✅ Test Your Mental Model
🧠 Services & sync — do you have it?
0/4 · 0/4 answered1. A new service needs dealership + zone data. Where should it get it?
2. Which direction do ORDER MILESTONES flow?
3. Why publish intents to a topic instead of calling Salesforce inline during checkout?
4. Odyssey publishes an inventory delta. Who reacts?
Architecture overview generated from internal repo READMEs and design docs. Purpose-and-flow only — infrastructure identifiers intentionally omitted.