An order HTTP service demonstrating validation-driven boundaries today and a full lifecycle core — state machines, idempotency, optimistic concurrency and a transactional outbox — as the target.
In development · Backend runtime: Local development only · Demo data source: Mock
Scope
A backend engineering case study of order creation, lifecycle state and payment semantics for a technical demo environment.
Not in scope
Not a storefront or product catalog.
Not an inventory system.
Not a real acquiring/payment-provider integration.
Engineering focus
State machines, transactions, idempotency, optimistic concurrency, transactional outbox.
State machines, transactions, idempotency, optimistic concurrency, transactional outbox.
Current Implementation
Current
POST /orders validates the product field (trim + non-empty) and calls the service layer; GET /orders/{id} validates a positive integer ID and an optional details flag. Handlers return demonstration text without persistence.
HTTP handlers: POST /orders, GET /orders/{id} validation and service delegation — services/order-service/cmd/order-service/main.go · https://github.com/Officialsayp/zolotoy-dev-backend · e36b1025 · reviewed 2026-09-17
Independent domain models and transition methods exist in the module but are not yet connected to the HTTP flow.
Domain models and transition methods (separate from the HTTP flow) — services/order-service/internal/order · https://github.com/Officialsayp/zolotoy-dev-backend · e36b1025 · reviewed 2026-09-17
Current
No storage integration yet: created orders are not persisted and GET does not retrieve from storage.
HTTP handlers: POST /orders, GET /orders/{id} validation and service delegation — services/order-service/cmd/order-service/main.go · https://github.com/Officialsayp/zolotoy-dev-backend · e36b1025 · reviewed 2026-09-17
Current
No automated backend tests existed in the inspected inventory — handler/service/domain tests are part of the current milestone, not a completed fact.
Backend roadmap: Service Layer milestone in progress — docs/roadmap.md · zolotoy-dev-backend · e36b1025 · reviewed 2026-09-17
Target Architecture
Target
Independent order and payment state machines with an explicit allowed-transition matrix, cancellation and refund paths, and versioned updates.
Order service specification (target contract) — docs/backend-specs/01_order_service.md · zolotoy-dev-frontend (this repository) · reviewed 2026-09-17
Target
PostgreSQL persistence with migrations, durable create/read, and transactions that keep external payment calls outside open database transactions.
Order service specification (target contract) — docs/backend-specs/01_order_service.md · zolotoy-dev-frontend (this repository) · reviewed 2026-09-17
Handler (net/http)POST /orders, GET /orders/{id}: trim, validate, delegate
Order serviceBusiness result construction (in development)
Domain modelsStatus/payment transitions — present but not connected
POST /orders {product}: client → handler
validated call: handler → service
not yet integrated: service → domain (planned)
Current order flow: HTTP boundary into the service layer, no storage.Target
HTTP clientJSON API consumers
HandlerDTO validation and error envelopes
Order serviceTransition matrix, idempotency, version checks
PostgreSQLOrders, history, outbox records
Outbox publisherAt-least-once event delivery
JSON API: client → handler
application boundary: handler → service
transactional writes: service → db (planned)
atomic event records: db → outbox (planned)
Target order flow: state machines, persistence, outbox.
Engineering Decisions
Validation lives at the HTTP boundary, business rules in the service layer
Handlers trim and validate input shape (product, ID, flags) and delegate; the service layer owns the result. Keeping transport parsing out of the service keeps the boundary testable without HTTP.
Domain models are built separately before wiring the HTTP flow
Order/payment state machines and transition methods are developed as an independent domain package first, so lifecycle semantics can be designed and tested before they are coupled to handlers and storage.
Idempotency keys scope to operation + payload
Target design: a repeated idempotency key with the same payload returns the original result; the same key with a different payload is a client error. This prevents both duplicate side effects and silent payload substitution.
External payment calls stay outside open database transactions
Target design: reserve state in a short transaction, call the provider outside it, then apply the result in a guarded transition. A crash between the two steps is recovered by reconciliation, not by holding locks across network I/O.
Reliability / Failure Modes
Repeated idempotency key: same payload vs different payload
Same payload → return the recorded result (no second side effect). Different payload → 409-style client error instead of silently reprocessing. The stored key must bind to a request fingerprint.
Competing Pay/Cancel operations
Two concurrent transitions on one order must serialize through the version check: exactly one wins, the loser gets a concurrency conflict and re-reads current state.
External payment call vs process crash
If the process dies between charging and recording, reconciliation (not a live transaction) resolves the outcome; the order records an in-flight payment state rather than pretending nothing happened.
Outbox publication duplicates
Outbox delivery is at-least-once: consumers must deduplicate by event ID. Publishers do not promise exactly-once.
Evidence
HTTP handlers: POST /orders, GET /orders/{id} validation and service delegation — services/order-service/cmd/order-service/main.go · https://github.com/Officialsayp/zolotoy-dev-backend · e36b1025 · reviewed 2026-09-17