Application reference. This is an illustrative architecture and scope checklist, not a verified customer project or measured deployment. Technologies, integration scope and delivery items are agreed for the actual brief.
Scenario and Constraints
A retail brand selling through a WeChat mini program while also running physical stores. The hard requirement is that stock stays correct across channels during promotions: independently updated channel stock can create overselling risk unless reservation, synchronization and reconciliation rules are defined. Membership points and coupons must also settle consistently, because a discount applied twice is a direct financial loss.
Architecture
Layers and responsibilities
| Layer | Technology | What it is responsible for |
|---|---|---|
| Client | UniApp (WeChat + Douyin from one codebase) | Catalog browsing, cart, checkout, member centre. No business rule is trusted here; the client only renders state the server confirmed. |
| API | Go + Gin, stateless behind a load balancer | Request validation, authentication, business rules, transaction boundaries. Horizontally scalable because no session state lives in the process. |
| Cache | Redis | Hot catalog data, stock counters for flash sales, distributed locks, idempotency keys for payment callbacks. |
| Storage | MySQL with read replica | Authoritative data. Writes go to the primary; catalog and report reads can be routed to a replica once read load justifies it. |
| Admin | Vue 3 + Element Plus | Catalog, order, inventory, promotion and store management with backend-enforced permissions. |
| Async | Queue workers | Payment reconciliation, message pushes, report aggregation, stock release on order timeout — anything that must not block the checkout request. |
Data Model
The tables below carry the rules that everything else depends on. Getting these wrong is what turns a working demo into a system that cannot be extended.
Core entities
| Entity | Key fields, relations and rules |
|---|---|
| product / sku | One product maps to many SKUs by attribute combination. Price and stock hang off the SKU, never the product, otherwise multi-variant pricing becomes impossible to extend. |
| inventory | Rows keyed by (sku_id, location_id) holding on_hand and reserved. Available stock is derived as on_hand minus reserved; transactions and reconciliation still need testing to detect discrepancies. |
| inventory_txn | Append-only ledger of every stock movement with reason code and source order. Current stock must always be reproducible by replaying this ledger — this is what makes discrepancies auditable instead of arguable. |
| order / order_item | Order carries the state machine and totals; items snapshot the SKU title, spec and unit price at purchase time so later catalog edits cannot rewrite order history. |
| payment_txn | Gateway transaction id, amount, status and raw callback payload. Unique on the gateway id so a repeated WeChat Pay callback cannot be applied twice. |
| member / point_txn / coupon | Member balance and points are derived from an append-only transaction log. Coupon rows carry scope, threshold, stacking priority and a used_at stamp used for single-use enforcement. |
Key Interfaces
Endpoints that carry the business rules
| Endpoint | Purpose and concurrency notes |
|---|---|
| POST /api/v1/orders | Creates the order and reserves stock inside one database transaction. Under flash-sale load the reservation goes through an atomic Redis decrement first, with MySQL as the settlement of record; the client passes an idempotency key so a double tap cannot create two orders. |
| POST /api/v1/payments/callback | Gateway callback. Idempotent on the gateway transaction id, verifies the signature, and moves the order state forward. Returns success only after the state change is committed, otherwise the gateway keeps retrying. |
| POST /api/v1/orders/{id}/cancel | Releases reserved stock and reverses coupon and point usage in the same transaction that closes the order. |
| GET /api/v1/skus/{id}/availability | Reads available stock through cache with a short TTL. Displayed availability is intentionally allowed to lag; only the order transaction is authoritative. |
| POST /api/v1/admin/inventory/adjust | Writes an inventory_txn with a reason code and operator id rather than updating a stock number directly. Every manual correction stays traceable. |
Technical Decisions
- UniApp over separate native mini programs. WeChat and Douyin share most of the commerce flow, so one codebase removes duplicated maintenance. Platform-specific payment and login are isolated behind an adapter layer rather than sprinkled through the pages.
- Stock reserved at order placement, not at payment. Reserving at payment time means a customer can pay for something already sold. The trade-off is that unpaid orders hold stock, so reservations expire on a timer and a worker releases them.
- Availability derived, never stored. A cached available_qty value introduces another synchronization path. Derived availability can reduce that duplication; compare read performance and reconciliation behavior for the actual workload.
- Append-only ledgers for stock, points and balance. Any figure customers may dispute must be reconstructible from a log, otherwise support has no way to explain a discrepancy.
- Go for the API layer. The workload is many short concurrent requests around a database, which suits Go's concurrency model, and a single static binary keeps deployment and rollback simple.
Hypothetical Design Targets
The figures below are hypothetical capacity-planning examples, not measured client results, a validated sizing recommendation or an SLA. Set project-specific acceptance targets after defining the workload, devices, data, hardware and third-party dependencies; verify them through a pilot and load tests before committing to a production target.
Capacity and performance targets
| Target | Value and assumption |
|---|---|
| Catalog read latency | p95 under 150 ms at the API, assuming hot data in Redis and a database on the same private network. |
| Order creation | p95 under 400 ms including stock reservation, on a single primary database with order tables indexed on (site_id, status, created_at). |
| Flash-sale burst | Order path sized for a few thousand requests per minute per SKU through Redis atomic decrement before MySQL settlement. Beyond that, queue-based admission is added — the threshold is confirmed by load testing against your real data volume. |
| Payment callback | Processed idempotently within the gateway retry window; duplicate callbacks are rejected on the unique gateway transaction id. |
What Delivery Includes
- Mini program source, Go backend source and Vue admin source in your repository
- Database schema with migrations, index rationale and the ledger tables documented
- API documentation covering authentication, error codes and idempotency requirements
- Deployment notes for Linux, Docker and Nginx, plus backup and restore procedure
- Payment and message account integration support; platform review outcome remains with WeChat or Douyin
Planning This for Your Business
The modules above are a starting point, not a fixed package. We normally cut the first release to one core workflow plus one admin workflow, then extend once real usage shows where the load and the edge cases actually are. Send a scoped brief and we will map it against this architecture and tell you which parts you do not need yet.

