Shop It Docs
Developer Resourcesorder

Order Module Backend Documentation

Order Module - Backend Documentation

1. Backend Scope and Boundaries

Order backend owns:

  • checkout and buy-now initiation
  • order state transitions and status history
  • async order commands (cancel/process-refund)
  • payment callback-driven finalization handoff
  • outbox dispatch and retention cleanup for order-owned maintenance runtime

Order domain supports:

  • payment_method: online

order_payment_method is intentionally constrained to online today. The enum remains in place as a forward-compatible contract so future payment methods can be introduced through coordinated migrations and client rollout.

2. Module Composition (Aggregate + Leaf)

OrderModule composes:

  • OrderCoreModule
  • OrderCustomerModule
  • OrderAdminModule
  • OrderProcessingModule

Ownership model:

  • OrderCoreModule exports shared domain service (OrderService)
  • customer/admin modules own their HTTP surfaces
  • OrderProcessingModule owns queues, processors, maintenance scheduler, outbox dispatch, and cleanup

3. Data Model (Drizzle / PostgreSQL)

Primary tables:

  • order
  • order_item
  • order_status_history
  • async_request
  • outbox_event

Schema source of truth:

  • packages/db/src/schema/order/enums.ts
  • packages/db/src/schema/order/orders.ts
  • packages/db/src/schema/order/order-items.ts
  • packages/db/src/schema/order/order-status-history.ts

Monetary integrity constraints (paisa):

  • order totals: total_mrp, total_sp, discount, coupon_discount, final_payable, refund_amount
  • order line values: unit_mrp, unit_sp, discount, final_value
  • DB check constraints enforce non-negative values.

Actor provenance model (order_status_history):

  • actor_type = customer + created_by_customer_id
  • actor_type = admin + created_by_admin_id
  • actor_type = system + both null

4. Runtime Rules and Domain Invariants

4.1 Synchronous initiation paths

  • POST /api/orders/checkout
  • POST /api/orders/buy-now

These create order/payment intent synchronously and return payment initiation payload immediately.

Buy-now product mapping:

  • physical products (thangka, singing_bowl, statue, jewellery) create order_type = physical

4.2 Asynchronous finalization and commands

  • payment success/failure jobs from payment redirect events
  • retry reconciliation (order.payment_retry)
  • auto-cancel for unpaid orders (order.auto_cancel)
  • async customer/admin cancellation and refund processing (order.cancel, order.process_refund)

4.3 Payment redirect contract

Gateway verification uses backend-owned redirect handlers:

  • GET|POST /api/payments/redirect/:paymentId/success
  • GET|POST /api/payments/redirect/:paymentId/failure

Return URL and callback URL resolution use runtime config (API_PUBLIC_BASE_URL, FRONTEND_BASE_URL, PAYMENT_RESULT_PAGE_URL).

4.4 Idempotency and atomicity

  • idempotency-key replay for checkout/buy-now is deterministic
  • async request dedupe via async_requests
  • outbox dedupe via (aggregate_type, aggregate_id, job_name, dedupe_key)
  • queue jobs use deterministic jobId
  • multi-table mutations execute in DB transactions

4.5 Payment success artifact creation

On successful payment, processor finalizes order state and emits inventory-finalization outbox events:

  • physical products transition through reserve -> finalize inventory lifecycle

4.6 Queues used by order runtime

  • orders
  • orders_maintenance
  • cart (outbox dispatch target for cart-clear intent)

4.7 Outbox lifecycle and cleanup behavior

outbox_events is shared infrastructure. Order runtime writes outbox events while maintenance runtime handles dispatch and retention cleanup.

Dispatch ownership:

  • OutboxDispatcherService claims pending rows only for owned target queues:
    • orders
    • orders_maintenance
    • cart

Cleanup flow:

  1. OrdersMaintenanceScheduler enqueues orders_maintenance.cleanup_outbox.
  2. OrdersMaintenanceProcessor runs OutboxCleanupService.cleanup().
  3. Completed rows older than OUTBOX_RETENTION_DAYS and failed rows older than OUTBOX_FAILED_RETENTION_DAYS are removed in batches.
  4. DLQ health check compares failed-job count against OUTBOX_CLEANUP_DLQ_THRESHOLD and emits alert-level logs on breach.

5. Caching Strategy

Read-side keyspaces:

  • order:*
  • order:customer:list:*
  • order:admin:list:*
  • order:admin:detail:*

Cross-module keys invalidated by order processing when applicable:

Configured TTLs:

  • ORDER_HISTORY_CACHE_TTL_SECONDS (default 120)
  • ORDER_ADMIN_CACHE_TTL_SECONDS (default 60)

6. Rate Limiting Strategy

Customer-side controls:

  • ORDER_CHECKOUT_RATE_LIMIT (default 10)
  • ORDER_RETRY_PAYMENT_RATE_LIMIT (default 5)
  • ORDER_CANCEL_RATE_LIMIT (default 10)
  • ORDER_REFUND_REQUEST_RATE_LIMIT (default 5)
  • ORDER_CHECKOUT_RATE_WINDOW_SECONDS (default 60)

Admin-side controls:

  • ORDER_ADMIN_OPERATION_RATE_LIMIT (default 120)
  • ORDER_ADMIN_RATE_WINDOW_SECONDS (default 60)

All rate limiting paths use Redis-backed counters/sliding windows and throw RateLimitExceededException on breach.

Additional order runtime knobs:

  • ORDER_AUTO_CANCEL_MINUTES (default 30)
  • ORDER_PAYMENT_RETRY_MAX_ATTEMPTS (default 3)
  • OUTBOX_RETENTION_DAYS (default 7)
  • OUTBOX_FAILED_RETENTION_DAYS (default 30)
  • OUTBOX_CLEANUP_ENABLED (default true)
  • OUTBOX_CLEANUP_CRON (default 0 3 * * *)
  • ORDERS_DISPATCH_CRON (default * * * * *)
  • ORDERS_FAILED_MONITOR_CRON (default */5 * * * *)
  • OUTBOX_CLEANUP_DLQ_THRESHOLD (default 100)
  • DLQ_WARNING_THRESHOLD (default 50)
  • OUTBOX_BATCH_SIZE (default 300)
  • OUTBOX_PENDING_PREVIEW_LIMIT (default 10)
  • RETRY_BASE_DELAY_MS (default 2000)
  • RETRY_MAX_DELAY_MS (default 120000)
  • PAYMENT_RETRY_DELAY_ATTEMPT_1_MS (default 60000)
  • PAYMENT_RETRY_DELAY_ATTEMPT_2_MS (default 300000)
  • PAYMENT_RETRY_DELAY_ATTEMPT_3_MS (default 900000)
  • WORKER_ORDERS_CONCURRENCY (default 20)
  • WORKER_ORDERS_MAINTENANCE_CONCURRENCY (default 8)

7. Error and Resilience Contracts

Representative API/domain errors:

HTTPerrorCodeMessage
400ORDER_CART_INACTIVEOnly active cart can be checked out.
400ORDER_CART_EMPTYCart has no items.
400ORDER_PAYMENT_AMOUNT_MISMATCHPayment amount mismatch detected.
400ORDER_PRODUCT_NOT_AVAILABLEProduct is not available for purchase.
400ORDER_PAYMENT_METHOD_NOT_SUPPORTEDOnly online payment is supported.
400ORDER_CANCEL_NOT_ALLOWEDOrder cannot be cancelled in current status.
400ORDER_NOT_PENDING_REFUNDOrder is not pending refund processing.
400ORDER_NOTE_REQUIREDNote is required.
403ORDER_REFUND_ACCESS_DENIEDYou do not have permission to request refund for this order.
404ORDER_CART_NOT_FOUNDCart not found.
404ORDER_ASYNC_REQUEST_NOT_FOUNDAsync request not found.
404ORDER_NOT_FOUNDOrder not found.
409ORDER_IDEMPOTENCY_MISMATCHRequest with this idempotency key is already in progress.
503ORDER_ASYNC_REQUEST_CREATION_FAILEDFailed to create async order request.
503ERR_CONFIG_INVALIDConfiguration value is missing/invalid.
429RATE_LIMIT_EXCEEDEDToo many requests. Please try again later.

Resilience controls in processing runtime:

  • retry + backoff for queued failures
  • queue failed-set threshold monitoring (DLQ_WARNING_THRESHOLD, QUEUE_FAILED_THRESHOLD_*)
  • outbox retention cleanup with separate thresholds (OUTBOX_CLEANUP_DLQ_THRESHOLD)

8. Performance Notes

  • Services use select projections instead of broad row selection for list/detail views.
  • Pagination is normalized and translated via PaginationUtil, with count queries only when pagination is enabled.
  • Independent operations use Promise.all(...) in critical paths (for example, outbox dispatcher scan and cleanup stats).
  • Hot order list/detail reads are cached in Redis with deterministic cache keys.
  • Processor cache invalidation is prefix-based (invalidatePattern(prefix*)) to avoid stale reads after async state transitions.

9. Backend Diagram

10. Release/QA Checklist

  • Checkout/buy-now initiation remains synchronous and returns gateway payload.
  • Payment redirect callbacks enqueue correct order jobs for success/failure.
  • Cancel/refund async commands create pollable async requests and deterministic job ids.
  • Status history entries preserve actor provenance constraints.
  • Payment success replay does not duplicate entitlement artifacts.
  • Outbox dispatcher only claims owned target queues (orders, orders_maintenance, cart).
  • Outbox cleanup retention and DLQ threshold behavior is validated in non-prod run.
  • Runtime env defaults are present and pass startup validation.

11. File Map

  • apps/api/src/modules/order/admin/*
  • apps/api/src/modules/order/customer/*
  • apps/api/src/modules/order/processing/*
  • packages/db/src/schema/order/*

12. Environment Variables

VariableDefaultDescription
ORDER_CHECKOUT_RATE_LIMIT10Rate limit for checkout requests per window
ORDER_CHECKOUT_RATE_WINDOW_SECONDS60Rate limit window in seconds for checkout
ORDER_RETRY_PAYMENT_RATE_LIMIT5Rate limit for retry payment requests
ORDER_RETRY_PAYMENT_RATE_WINDOW_SECONDS60Rate limit window for retry payment
ORDER_CANCEL_RATE_LIMIT10Rate limit for order cancellation requests
ORDER_CANCEL_RATE_WINDOW_SECONDS60Rate limit window for cancellation
ORDER_REFUND_REQUEST_RATE_LIMIT5Rate limit for refund request submissions
ORDER_REFUND_REQUEST_RATE_WINDOW_SECONDS60Rate limit window for refund requests
ORDER_ADMIN_OPERATION_RATE_LIMIT120Rate limit for admin order operations
ORDER_ADMIN_RATE_WINDOW_SECONDS60Rate limit window for admin operations
ORDER_HISTORY_CACHE_TTL_SECONDS120Cache TTL for order history in seconds
ORDER_ADMIN_CACHE_TTL_SECONDS60Cache TTL for admin order views in seconds
ORDER_AUTO_CANCEL_MINUTES30Minutes before unpaid orders are auto-cancelled
ORDER_PAYMENT_RETRY_MAX_ATTEMPTS3Maximum payment retry attempts
OUTBOX_RETENTION_DAYS7Days to retain completed outbox events
OUTBOX_FAILED_RETENTION_DAYS30Days to retain failed outbox events
OUTBOX_CLEANUP_ENABLEDtrueEnable outbox cleanup job
OUTBOX_CLEANUP_CRON0 3 * * *Cron schedule for outbox cleanup
ORDERS_DISPATCH_CRON* * * * *Cron schedule for orders dispatch
ORDERS_FAILED_MONITOR_CRON*/5 * * * *Cron schedule for failed order monitoring
OUTBOX_CLEANUP_DLQ_THRESHOLD100DLQ threshold for outbox cleanup alerts
DLQ_WARNING_THRESHOLD50Warning threshold for failed jobs
OUTBOX_BATCH_SIZE300Batch size for outbox processing
OUTBOX_PENDING_PREVIEW_LIMIT10Preview limit for pending outbox events
RETRY_BASE_DELAY_MS2000Base delay for retry backoff in milliseconds
RETRY_MAX_DELAY_MS120000Maximum retry delay in milliseconds
PAYMENT_RETRY_DELAY_ATTEMPT_1_MS60000Delay before first payment retry
PAYMENT_RETRY_DELAY_ATTEMPT_2_MS300000Delay before second payment retry
PAYMENT_RETRY_DELAY_ATTEMPT_3_MS900000Delay before third payment retry
WORKER_ORDERS_CONCURRENCY20Worker concurrency for orders queue
WORKER_ORDERS_MAINTENANCE_CONCURRENCY8Worker concurrency for maintenance queue

Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.


See Also