Case study · product / system
Revo — a recommerce platform built around the parts that fail.
A consumer recommerce flow shipped to production. The interesting engineering is not the storefront — it's the request shaping, valuation logic, state machine, and the operator console that absorbs every edge case.
A small operations team handling a high-variance intake.
The team running Revo was a handful of operators evaluating used consumer electronics at volume. Customers submitted devices through a public form and expected a quote within minutes. Each device was different — model, condition, accessories, regional pricing — and the team had no internal tooling to keep evaluations consistent across days, shifts, or operators.
The brief was: ship a public quote-to-fulfillment flow that operators could actually run, not a marketing page that generates leads for someone else to deal with.
Free-text intake, manual valuations, no audit trail.
- Customers described devices in unstructured prose; intake quality varied per submission.
- Every quote required a human review, even on routine models the team had priced 100 times before.
- Once an order moved into payment / shipping, status updates were ad-hoc emails — operators couldn't reconstruct what happened when a buyer disputed a transaction.
- Edge cases (locked devices, mismatched IMEIs, partial accessories) had no defined handling path; each one was solved from scratch.
End-to-end engineering, from form schema to operator console.
-
Owned
System architecture, database schema, request validation, valuation engine, order state machine, operator console, deployment.
-
Shared
Pricing rules with the operations lead; UX flow with one designer; payment integration review with finance.
-
Reporting
Direct line to the founder; weekly demo of operator console with real orders.
One pipeline, four cooperating layers.
- Quote intake. Guided form turns a device + condition + accessories into a structured request before any payment or account is created. Schema is the contract every downstream layer reads from.
- Valuation engine. Rules + condition modifiers + regional pricing produce a quote band. A
review_requiredflag short-circuits to operator review when the rules can't decide with confidence. - Order state machine. Checkout, payment, label generation, in-transit tracking, received, inspected, settled — each transition is logged with actor, timestamp, and reason. Idempotent transitions; no "what state is this order in" ambiguity.
- Operator console. Lists exception orders first, then in-progress, then closed. Every action an operator takes (override valuation, request more info, cancel, settle) writes back into the same state log the customer sees.
Boring stack on purpose.
- PHP 8
- MySQL 8
- Vanilla JS
- MQTT (device telemetry)
- Stripe (payments)
- EasyPost (labels)
- Apache + .htaccess routing
No SPA framework. No queue worker. No Redis. The traffic and team size didn't justify the complexity — and stripping operational surface area meant the operator team could read the codebase when they wanted to understand a behavior.
Trade-offs I'd make again.
-
Schema-first
The intake schema was the first thing built and the last thing changed. Every layer downstream agreed on the same shape, which is why valuation, fulfillment, and reporting all read from one source.
-
State machine over status field
Explicit transitions with allowed-from / allowed-to lists. Made dispute resolution provable instead of forensic.
-
Operator console = first-class
Built the operator surface in the same sprint as the customer surface, not after. Forced edge cases out into the open early.
-
Manual review as a feature
Treated
review_requiredas a real outcome, not a fallback. The valuation engine is allowed to say "I don't know" — the alternative is bad quotes the team has to undo later.
What the team could do after that they couldn't before.
Routine quotes resolve without operator touch; only review_required orders enter the queue. The operator team's time shifts from typing quotes to handling exceptions.
Every state transition is timestamped with an actor and reason. Disputes are resolvable from the order's own log instead of email threads.
Reporting and dispute resolution read the same data the customer sees. One source of truth, three audiences.
Specific volume and dollar figures are owned by the operator; happy to share under NDA on request.
Honest follow-ups, not future-proofing.
- Replace the per-row pricing config with a versioned ruleset table so operators can roll back a bad pricing change in one query.
- Move the valuation engine behind an internal API; right now the customer-facing PHP imports it directly. Same code, cleaner boundary.
- Add structured event emission (
order.transitioned,quote.flagged) — not because we need a queue today, but so we have the option later without rewriting the call sites. - Add deterministic seed data for the operator console so onboarding a new operator doesn't depend on production traffic that day.