Architecture Review: E-Commerce Order Platform
An e-commerce order lifecycle platform handling cart, checkout, payment, fulfillment, and returns across a mixed read/write workload where product discovery is read-heavy, checkout is write-transactional, and fulfillment is event-driven. The saga pattern orchestrates multi-step checkout: reserve inventory → charge payment → confirm order → notify fulfillment. PostgreSQL owns order records and inventory with row-level locking; Redis holds session state and cart contents with sub-millisecond access; RabbitMQ delivers fulfillment notifications with dead-letter handling; Elasticsearch serves product search and order history with faceted navigation. CQRS separates the write command path from the read model: the order read model is denormalized for fast order history queries without joining across domain tables.
Evidence Confidence
Moderate
strong
Executive Summary
E-Commerce Order Platform: moderate operational readiness (81% evidence confidence). 0 architectural strengths identified, 6 operational risks to manage. Primary concern: Cascading Failure. Requires Advanced operational maturity.
Readiness Rationale
Overall moderate readiness across 8 dimensions. Limited: scaling, team maturity. Strong: migration, observability, failure recovery.
Key Concerns
- !Cascading Failure
- !Lock Contention
Key Strengths
- +Architecture is well-defined for the marketplace platform problem profile
8
Assessments
4
Tradeoffs
6
Sections
11
Recommendations
Readiness Assessments
8Architectural Tradeoffs
4Recommendations
11Monitor: Lock Contention
risk_monitoringConcurrent writers to the same rows serialize behind each other's row locks, so latency is set not by the work a transaction does but by how long it waits for the writers ahead of it. On a hot row the queue depth, and therefore the tail latency, grows with concurrency while throughput flattens. Blocked writers hold connections open, so a single contended row can drain the connection pool as a secondary failure.
Affects 0 nodes
Monitor: Cascading Failure
risk_monitoringA failure or degradation in one service causes increased load, held resources, or error propagation in its callers, which in turn degrade their callers, until the failure front propagates through the entire dependency graph and brings down services with no direct dependency on the original failure point.
Affects 0 nodes
Implement: Monitor generic risk probe signals
observabilitySeed 'Thundering Herd (Cache Stampede) Risk Probe' identifies 2 metrics relevant to thundering_herd.
Metrics to instrument: error_rate, p95_latency_ms
Synchronous checkout with direct database payment insert and synchronous payment API call → Saga-orchestrated checkout with outbox-based fulfillment events
migration_planningTrigger: Payment provider timeout causing full checkout rollback and user-facing error; fulfillment system outage causing checkout to fail synchronously rather than queue the fulfillment work; inability to replay failed fulfillment notifications after downstream system recovery. Migrate from 'Synchronous checkout with direct database payment insert and synchronous payment API call' to 'Saga-orchestrated checkout with outbox-based fulfillment events'. Implement the outbox pattern and fulfill-via-event flow first, before the full saga orchestrator. Validate that fulfillment events are reliably delivered across payment provider failures before implementing compensation logic.
Saga compensation paths for every checkout failure scenario must be designed before deployment: partial saga implementation is more dangerous than no saga; Idempotency keys for the payment provider must be persisted before the payment call, not after: a crash between these two events causes a payment charge with no local record
PostgreSQL full-text search for product discovery → Elasticsearch for product search with CDC-based catalog indexing
migration_planningTrigger: Product search p99 > 1s; faceted navigation (category + price range + brand + availability) requiring full-table scans in PostgreSQL; ranking by popularity or relevance score not achievable in PostgreSQL without full-table aggregation. Migrate from 'PostgreSQL full-text search for product discovery' to 'Elasticsearch for product search with CDC-based catalog indexing'. Run Elasticsearch in shadow mode for 2 weeks before serving traffic. Compare search result sets between PostgreSQL full-text and Elasticsearch for a representative query sample. Validate CDC latency meets the acceptable price staleness window.
Elasticsearch index must be seeded from PostgreSQL before CDC takes over: the initial bulk import must complete without catalog updates being lost during the window; Search result prices are eventually consistent with PostgreSQL: checkout must re-validate price at order creation, not trust the search result price
Prepare runbook for: Burst Traffic Cold Cache Stampede
simulation_preparednessSimulation demonstrates critical degradation of redis, postgresql
Without a runbook, recovery from this failure mode will be ad-hoc
Prepare runbook for: Connection Pool Exhaustion with Horizontal User Scale
simulation_preparednessSimulation demonstrates critical degradation of postgresql
Without a runbook, recovery from this failure mode will be ad-hoc
Plan evolution: OLTP Analytics Queries → OLTP + OLAP Separation
evolution_planningEvolution from Unified OLTP + Analytics on PostgreSQL → Separated OLTP (PostgreSQL) + OLAP (ClickHouse/Snowflake)
Migration complexity: medium. Rollback: always.
Plan evolution: Single Cache Layer → Distributed Cache
evolution_planningEvolution from Single Redis Node / Sentinel Cluster → Distributed Redis Cluster (Consistent Hash Ring)
Migration complexity: medium. Rollback: complex.
Monitor threshold: Tier 1: Flash Sale Inventory Contention
scaling_monitoringSignal: PostgreSQL pg_locks showing high RowExclusiveLock contention on inventory_items for specific sku_ids; checkout p99 > 2s for contended SKUs; deadlock errors appearing in application logs during sale events; effective checkout throughput for hot SKUs well below per-request checkout latency would predict
Bottleneck: Concurrent saga checkout attempts competing for the same inventory row via row-level locking. Evolution: Introduce a per-SKU checkout serialization queue at the application layer : all concurrent checkout requests for the same SKU are queued and processed serially, converting lock contention into queue latency. Alternatively, use PostgreSQL advisory locks with non-blocking trylock: requests that cannot acquire the lock immediately return a "sold out" response rather than queuing. For very high flash sale volumes, pre-allocate inventory slots (reserve N slots per sale event, each slot is a row with one reservation) to spread lock contention across N rows instead of one.
Monitor threshold: Tier 2: Payment Provider Latency Amplifying Checkout Latency
scaling_monitoringSignal: Checkout p99 tracking payment provider p99 almost linearly; connection pool utilization on the payment service rising during payment provider slowdowns; circuit breaker trip events appearing in payment service metrics; saga timeout events correlated with payment provider latency spikes
Bottleneck: Checkout saga holding a database connection and an inventory reservation open for the duration of the payment provider call: payment latency directly amplifies connection pool pressure. Evolution: Decouple the payment step from the synchronous checkout saga: reserve inventory and create the order record synchronously, then process payment asynchronously. The customer receives an "order confirmed, payment processing" state immediately; the payment step runs as a separate saga step triggered by an event. This reduces the synchronous checkout latency to the inventory reservation time, not the payment provider round-trip time.
Scaling Pressure Signals
8PostgreSQL pg_locks showing high RowExclusiveLock contention on inventory_items for specific sku_ids; checkout p99 > 2s for contended SKUs; deadlock errors appearing in application logs during sale events; effective checkout throughput for hot SKUs well below per-request checkout latency would predict
Threshold
Tier 1: Flash Sale Inventory Contention
Likely Bottleneck
Concurrent saga checkout attempts competing for the same inventory row via row-level locking
Recommended Evolution
Introduce a per-SKU checkout serialization queue at the application layer : all concurrent checkout requests for the same SKU are queued and processed serially, converting lock contention into queue latency. Alternatively, use PostgreSQL advisory locks with non-blocking trylock: requests that cannot acquire the lock immediately return a "sold out" response rather than queuing. For very high flash sale volumes, pre-allocate inventory slots (reserve N slots per sale event, each slot is a row with one reservation) to spread lock contention across N rows instead of one.
Checkout p99 tracking payment provider p99 almost linearly; connection pool utilization on the payment service rising during payment provider slowdowns; circuit breaker trip events appearing in payment service metrics; saga timeout events correlated with payment provider latency spikes
Threshold
Tier 2: Payment Provider Latency Amplifying Checkout Latency
Likely Bottleneck
Checkout saga holding a database connection and an inventory reservation open for the duration of the payment provider call: payment latency directly amplifies connection pool pressure
Recommended Evolution
Decouple the payment step from the synchronous checkout saga: reserve inventory and create the order record synchronously, then process payment asynchronously. The customer receives an "order confirmed, payment processing" state immediately; the payment step runs as a separate saga step triggered by an event. This reduces the synchronous checkout latency to the inventory reservation time, not the payment provider round-trip time.
CDC consumer lag on the Elasticsearch indexing consumer > 30s during catalog bulk updates; customer complaints about price changes not visible in search; search result prices diverging from checkout prices by more than the acceptable window; Kibana showing indexing throughput below the catalog update rate
Threshold
Tier 3: Elasticsearch Index Staleness During High Catalog Update Rate
Likely Bottleneck
Elasticsearch bulk indexing throughput insufficient to keep pace with high-volume catalog update events from Kafka
Recommended Evolution
Tune Elasticsearch bulk indexing batch size and flush interval to increase indexing throughput; add indexing consumer replicas with partition-based assignment to parallelize indexing across catalog segment partitions. Introduce a "price_as_of" timestamp in search results displayed to customers : this converts an invisible consistency gap into an explicit, auditable staleness signal that satisfies most checkout price dispute scenarios.
PostgreSQL primary CPU > 75% sustained under combined checkout + catalog write + order history read workloads; domain team schema migrations blocking each other; connection pool exhausted by combined connection demand from checkout, catalog, and order history services sharing the same pool
Threshold
Tier 4: Domain Decomposition Pressure from Shared PostgreSQL
Likely Bottleneck
Shared PostgreSQL primary serving multiple distinct domain workloads: catalog writes, order transactions, and return processing all competing for the same resource pool
Recommended Evolution
Decompose into catalog database (product data, inventory), orders database (orders, payments, returns), and user database (sessions, preferences) using database-per-service pattern. Each domain gets its own connection pool and its own schema migration lifecycle. Cross-domain data access moves to events or API calls: direct cross-database JOINs are eliminated.
PostgreSQL pg_locks showing high RowExclusiveLock contention on inventory_items for specific sku_ids; checkout p99 > 2s for contended SKUs; deadlock errors appearing in application logs during sale events; effective checkout throughput for hot SKUs well below per-request checkout latency would predict
Threshold
Escalation trigger: Concurrent saga checkout attempts competing for the same inventory row via row-level locking
Likely Bottleneck
Tier 1: Flash Sale Inventory Contention
Recommended Evolution
Monitor: error_rate, p95_latency_ms
Checkout p99 tracking payment provider p99 almost linearly; connection pool utilization on the payment service rising during payment provider slowdowns; circuit breaker trip events appearing in payment service metrics; saga timeout events correlated with payment provider latency spikes
Threshold
Escalation trigger: Checkout saga holding a database connection and an inventory reservation open for the duration of the payment provider call: payment latency directly amplifies connection pool pressure
Likely Bottleneck
Tier 2: Payment Provider Latency Amplifying Checkout Latency
Recommended Evolution
Monitor: error_rate, p95_latency_ms
CDC consumer lag on the Elasticsearch indexing consumer > 30s during catalog bulk updates; customer complaints about price changes not visible in search; search result prices diverging from checkout prices by more than the acceptable window; Kibana showing indexing throughput below the catalog update rate
Threshold
Escalation trigger: Elasticsearch bulk indexing throughput insufficient to keep pace with high-volume catalog update events from Kafka
Likely Bottleneck
Tier 3: Elasticsearch Index Staleness During High Catalog Update Rate
Recommended Evolution
Monitor: error_rate, p95_latency_ms
PostgreSQL primary CPU > 75% sustained under combined checkout + catalog write + order history read workloads; domain team schema migrations blocking each other; connection pool exhausted by combined connection demand from checkout, catalog, and order history services sharing the same pool
Threshold
Escalation trigger: Shared PostgreSQL primary serving multiple distinct domain workloads: catalog writes, order transactions, and return processing all competing for the same resource pool
Likely Bottleneck
Tier 4: Domain Decomposition Pressure from Shared PostgreSQL
Recommended Evolution
Monitor: error_rate, p95_latency_ms
Migration Readiness
12Migration Stages
3Synchronous checkout with direct database payment insert and synchronous payment API call → Saga-orchestrated checkout with outbox-based fulfillment events
infoMigration trigger: Payment provider timeout causing full checkout rollback and user-facing error; fulfillment system outage causing checkout to fail synchronously rather than queue the fulfillment work; inability to replay failed fulfillment notifications after downstream system recovery
PostgreSQL full-text search for product discovery → Elasticsearch for product search with CDC-based catalog indexing
infoMigration trigger: Product search p99 > 1s; faceted navigation (category + price range + brand + availability) requiring full-table scans in PostgreSQL; ranking by popularity or relevance score not achievable in PostgreSQL without full-table aggregation
Monolithic order processing with inline notification delivery → RabbitMQ-based notification fanout with dead-letter handling
infoMigration trigger: Email/push notification provider timeouts causing checkout latency to increase proportionally; notification delivery failures causing order confirmation to appear failed even when the order was created successfully; inability to replay failed notification deliveries after provider recovery
Risks
9Saga compensation paths for every checkout failure scenario
warningSaga compensation paths for every checkout failure scenario must be designed before deployment: partial saga implementation is more dangerous than no saga
Idempotency keys for the payment provider must be persisted
warningIdempotency keys for the payment provider must be persisted before the payment call, not after: a crash between these two events causes a payment charge with no local record
Elasticsearch index must be seeded from PostgreSQL before CD
warningElasticsearch index must be seeded from PostgreSQL before CDC takes over: the initial bulk import must complete without catalog updates being lost during the window
Search result prices are eventually consistent with PostgreS
warningSearch result prices are eventually consistent with PostgreSQL: checkout must re-validate price at order creation, not trust the search result price
RabbitMQ queue depth must be monitored from day one: an unmo
warningRabbitMQ queue depth must be monitored from day one: an unmonitored queue during a warehouse system outage accumulates a backlog that causes a second incident on recovery
Dead-letter queue requires explicit operational runbook: mes
warningDead-letter queue requires explicit operational runbook: messages in the DLQ are not delivered until manually requeued or replayed
Projection lag creates a read-after-write window where users
criticalProjection lag creates a read-after-write window where users see stale data after their own writes. Mitigation: Route immediate post-write reads to the write store (session-scoped write token); accept eventual consistency only for non-user-initiated reads
↗ direct-db-to-cqrs
Projection rebuild after schema change can take hours or day
criticalProjection rebuild after schema change can take hours or days on large datasets. Mitigation: Design blue/green projection deployment: build new projection in parallel before switching traffic; test rebuild time in staging
↗ direct-db-to-cqrs
Cross-service workflows that previously used database transa
criticalCross-service workflows that previously used database transactions now require Saga orchestration. Mitigation: Design idempotent event handlers; implement compensating transactions for every multi-step workflow; test failure injection in staging
↗ modular-monolith-to-event-driven
Review Sections
6Referenced Intelligence