How to Auto‑Close Expired E‑Commerce Orders: Timers, Queues & Redis Time Wheels

Learn how to design and implement automatic order expiration in e‑commerce systems using three approaches—simple scheduled table scans, delayed message queues, and a Redis time‑wheel—detailing their trade‑offs, code examples, indexing tips, distributed locking, and failure‑handling strategies.

NiuNiu MaTe
NiuNiu MaTe
NiuNiu MaTe
How to Auto‑Close Expired E‑Commerce Orders: Timers, Queues & Redis Time Wheels

In e‑commerce platforms, orders that are created but never paid occupy inventory and coupons, turning into "zombie orders" that block resources. The core solution is to give each order an expiration time and automatically close it when the time elapses.

1. Scheduled Table Scan

This is the simplest method. A periodic task (using Spring Scheduled , Quartz, or XXL‑Job) scans the order table every 1–5 minutes, selects orders whose status is pending payment and whose creation time exceeds the configured validity period (typically 15–30 minutes), and closes them.

Typical SQL to find expired orders is illustrated below:

SQL query for expired orders
SQL query for expired orders

To keep the scan efficient on large tables, create a composite index on order_status and expire_time. A distributed lock (e.g., Redis SET NX) should be used so that only one instance processes a given batch.

2. Delayed Message Queue

Instead of repeatedly scanning the database, a delayed queue stores a “timer message” when the order is created. After the order’s validity period (e.g., 15 minutes) the message is delivered and triggers the closing logic.

Key steps:

When the order is created, deduct inventory, write the order record, and publish a delayed message containing order ID, user ID, creation time, and expiration time.

The message queue (RabbitMQ with dead‑letter + TTL, or RocketMQ with built‑in delayed messages) holds the message until the timeout.

When the message arrives, the consumer checks the current order status; if it is still pending payment the order is closed, otherwise the message is ignored.

This approach provides second‑level real‑time closing and scales well under high concurrency, but requires operating a separate MQ cluster.

3. Redis Time‑Wheel

A lightweight alternative that leverages Redis Sorted Set as a time wheel. Orders are added to a sorted set with the expiration timestamp as the score. A fast timer (often running every second) extracts orders whose score is less than or equal to the current time.

Step 1 – Insert order into the wheel:

# ZADD order:expire:timewheel 1757124900 "orderId:10086"
# HMSET order:info:10086 userId "12345" couponId "5678" createTime "1757124000"

Step 2 – Periodic task fetches due orders:

# ZRANGEBYSCORE order:expire:timewheel 0 1757125200 LIMIT 0 100

Step 3 – Remove the order atomically and process it: # ZREM order:expire:timewheel "orderId:10086" If ZREM returns 1, the worker proceeds to verify the order status in the database and close it; otherwise the order has already been handled by another worker.

After successful closing, delete the auxiliary hash: # DEL order:info:10086 Potential pitfalls and mitigations:

Data loss on Redis restart: enable RDB + AOF persistence.

Large sorted set slows queries: partition the wheel by hour (e.g., order:expire:timewheel:2024090210) and scan only the current and previous hour buckets.

Processing failures: add a fallback nightly scan of the database for orders still pending payment after their expiration.

All three solutions have trade‑offs. Table scanning is easy and requires no extra components but has poor real‑time performance. Delayed queues give the best latency and concurrency at the cost of operational overhead. The Redis time‑wheel sits in the middle, offering second‑level latency with minimal infrastructure, suitable for medium‑scale systems.

Redis time wheel diagram
Redis time wheel diagram
Comparison of three expiration strategies
Comparison of three expiration strategies
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

e-commercebackend designMessage Queuescheduled tasksorder expiration
NiuNiu MaTe
Written by

NiuNiu MaTe

Joined Tencent (nicknamed "Goose Factory") through campus recruitment at a second‑tier university. Career path: Tencent → foreign firm → ByteDance → Tencent. Started as an interviewer at the foreign firm and hopes to help others.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.