Danh mục:
1) Vì sao cần Promotion Engine riêng biệt?
- Marketing cần triển khai hàng trăm chiến dịch khuyến mãi song song
- Giảm giá, flash sale, voucher, combo, free shipping… rất đa dạng
- Phải đảm bảo áp dụng đúng điều kiện, không xung đột, không gây lỗi thanh toán
- Cần tracking hiệu quả khuyến mãi để ra quyết định kinh doanh
- Các sàn lớn như Shopee, Lazada… có Promotion Engine riêng tách khỏi hệ thống giỏ hàng/đơn hàng.
2) Tổng quan kiến trúc
[Client: Web/App] ↓ [Cart/Checkout Service] ↓ [Promotion Engine] ↓ [Pricing Engine] → [Order Service] ↓ [Analytics / Campaign Dashboard]
Promotion Engine hoạt động như bộ máy tính toán khuyến mãi độc lập, nhận dữ liệu giỏ hàng + user → trả về danh sách khuyến mãi áp dụng và số tiền giảm.
3) Các loại khuyến mãi phổ biến

4) Thiết kế dữ liệu Promotion
promotionpromotion_id, name, type (percent/fixed/threshold/flash/voucher…)
start_at, end_at, status
conditions: JSON (min_amount, category_id, product_id, user_segment…)
rewards: JSON (discount_percent, fixed_amount, free_shipping…)
max_uses_per_user, total_uses_limit
priority (giải quyết xung đột)
vouchercode, promotion_id, assigned_to_user, used_count, max_use
Dùng JSON schema linh hoạt để marketing tự tạo nhiều loại campaign mà không cần dev thêm field mới.
5) Luồng xử lý tính khuyến mãi
- Cart gửi request calculatePromotions(cart_id, user_id)
- Promotion Engine:
Lọc các promotion đang active
Kiểm tra điều kiện (conditions) → đủ điều kiện thì áp dụng
Ưu tiên theo priority → tránh trùng hoặc cộng dồn không mong muốn
Trả về danh sách promotion + tổng số tiền giảm
- Pricing Engine áp dụng số tiền giảm vào cart
- Khi user thanh toán thành công → mark promotion_used
Có thể hỗ trợ “stackable promotions” (cộng dồn) hoặc exclusive (chỉ áp dụng 1).
6) Flash Sale / Limited Stock
- Mỗi khuyến mãi flash có stock_limit riêng
- Khi checkout → gọi reservePromotionStock() (giống cơ chế giữ hàng)
- Dùng Redis + atomic decrement để tránh oversell
- Hết số lượng → tự động tắt khuyến mãi hoặc chuyển giá gốc
7) Performance & Scalability
- Dùng cache (Redis) để lưu promotion active
- Tránh query DB mỗi lần tính toán
- Dùng rule engine (Drools / custom DSL) để marketing tự định nghĩa điều kiện
- Dùng event-driven (Kafka) để đồng bộ cập nhật promotion
8) Tích hợp với hệ thống khác
- Cart Service: gửi dữ liệu sản phẩm → nhận về tiền giảm
- Order Service: xác nhận promotion đã dùng, đảm bảo tính nhất quán
- Inventory Service: giảm kho với flash sale
- Analytics: log promotion được áp dụng → tính ROI từng chiến dịch
- CMS: hiển thị banner campaign liên kết với promotion_id
9) Bảo mật và hạn chế gian lận
- Giới hạn max_uses_per_user, max_use_per_ip
- Gắn voucher vào user_id để không chia sẻ được
- Kiểm tra device_id, cookie_id tránh abuse tạo nhiều tài khoản
- Chống sửa request bằng chữ ký HMAC giữa client và server
10) Kết luận
Promotion Engine là “cỗ máy tạo doanh thu” trong hệ thống thương mại điện tử:
- Cho phép marketing tự tạo hàng trăm campaign phức tạp
- Tách biệt khỏi logic đơn hàng → giảm rủi ro
- Dễ mở rộng, scale cao trong mùa sale
- Theo dõi hiệu quả để tối ưu chiến lược
Gợi ý: Khi mới bắt đầu, hãy hỗ trợ 3 loại cơ bản (percent, fixed, threshold), sau đó dần bổ sung flash sale, voucher, bundle.