Real-World Project

E-Commerce Platform

Build a scalable shopping platform at Amazon scale with Cassandra!

๐Ÿ“– Project Overview

Build a real-world e-commerce platform!

The Challenge: ShopFast - Next-Gen E-Commerce

ShopFast is building the next Amazon. They need a database that can handle:

  • ๐Ÿ›๏ธ Product catalog: 100 million products
  • ๐Ÿ‘ฅ User activity: 50 million active users
  • ๐Ÿ›’ Shopping carts: Real-time cart updates
  • ๐Ÿ“ฆ Order history: 1 billion orders/year
  • โญ Reviews & ratings: Millions of reviews
  • ๐Ÿ” Search & browse: Sub-second product search

Scale Requirements

Products: 100 million SKUs across 10,000 categories
Users: 50 million monthly active users
Orders/Day: 2.7 million (1B/year รท 365)
Peak Traffic: Black Friday: 10x normal (27M orders/day)
Cart Updates: ~100K writes/second during peak
Product Views: 500K reads/second

Why Cassandra?

  • โœ… Linear scalability: Add nodes for Black Friday
  • โœ… High availability: Zero downtime during sales
  • โœ… Write throughput: 100K+ cart updates/second
  • โœ… Geo-distribution: Global data centers
  • โœ… Fast reads: Sub-10ms product lookups

๐ŸŽฏ Requirements & Use Cases

What we need to build!

๐Ÿ“ฆ

Product Catalog

  • Get product by ID (fast lookup)
  • Browse products by category
  • Search products by keywords
  • View product details & images
  • Check inventory availability
๐Ÿ›’

Shopping Cart

  • Add/remove items from cart
  • Update item quantities
  • View cart contents
  • Calculate cart total
  • Save cart across sessions
๐Ÿ“‹

Orders & History

  • Place order (checkout)
  • View order history
  • Track order status
  • Get order details
  • Reorder past items
โญ

Reviews & Ratings

  • Write product review
  • View all product reviews
  • Get average rating
  • Sort reviews (helpful, recent)
  • Review moderation

๐Ÿ—บ๏ธ Data Model Design

E-commerce data modeling!

E-Commerce Data Modeling Principles

  1. Denormalize for reads: Duplicate product data across tables
  2. User-centric partitions: user_id as partition key for personalized data
  3. Product-centric views: Separate tables for browsing catalog
  4. Time-bucketing: Orders partitioned by user + month
  5. Materialized views: Different access patterns = different tables

Query Patterns โ†’ Table Design

Query Pattern Access Pattern Table Design
Q1: Get product details By product_id products_by_id
Q2: Browse by category By category + price/popularity products_by_category
Q3: View shopping cart By user_id shopping_carts
Q4: Order history By user_id + date orders_by_user
Q5: Product reviews By product_id + date reviews_by_product
Q6: Get order details By order_id orders_by_id

E-Commerce Data Flow

            User Browses
                 โ”‚
                 โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Product Catalog       โ”‚
    โ”‚  - Browse categories   โ”‚
    โ”‚  - Search products     โ”‚
    โ”‚  - View details        โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚
             โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Shopping Cart         โ”‚
    โ”‚  - Add to cart         โ”‚
    โ”‚  - Update quantities   โ”‚
    โ”‚  - Calculate total     โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚
             โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Checkout Process      โ”‚
    โ”‚  - Create order        โ”‚
    โ”‚  - Payment             โ”‚
    โ”‚  - Inventory update    โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚
             โ–ผ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Order History         โ”‚
    โ”‚  - Track orders        โ”‚
    โ”‚  - View past orders    โ”‚
    โ”‚  - Reorder             โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        

๐Ÿ“‹ Schema Design

Complete table schemas!

1

Keyspace Creation

-- Create keyspace CREATE KEYSPACE shopfast WITH replication = { 'class': 'NetworkTopologyStrategy', 'us-east': 3, 'us-west': 3, 'eu-west': 3 }; USE shopfast;
2

Products Table (Primary Lookup)

-- Product details by ID (fast lookup) CREATE TABLE products_by_id ( product_id UUID PRIMARY KEY, name TEXT, description TEXT, brand TEXT, category TEXT, price DECIMAL, discount_percent DECIMAL, image_urls LIST<TEXT>, attributes MAP<TEXT, TEXT>, -- size, color, etc inventory_count INT, rating_avg DECIMAL, rating_count INT, created_at TIMESTAMP, updated_at TIMESTAMP ); -- Query: Get product details SELECT * FROM products_by_id WHERE product_id = ?;
3

Products by Category (Browse)

-- Products organized by category for browsing CREATE TABLE products_by_category ( category TEXT, -- Partition key price DECIMAL, -- Clustering key (sort) product_id UUID, -- Clustering key name TEXT, brand TEXT, image_url TEXT, rating_avg DECIMAL, discount_percent DECIMAL, PRIMARY KEY (category, price, product_id) ) WITH CLUSTERING ORDER BY (price ASC, product_id ASC); -- Query: Browse category by price SELECT * FROM products_by_category WHERE category = 'Electronics' LIMIT 50; -- Query: Filter by price range SELECT * FROM products_by_category WHERE category = 'Electronics' AND price >= 100 AND price <= 500;
4

Shopping Cart Table

-- User's shopping cart (fast read/write) CREATE TABLE shopping_carts ( user_id UUID, -- Partition key product_id UUID, -- Clustering key product_name TEXT, price DECIMAL, quantity INT, image_url TEXT, added_at TIMESTAMP, PRIMARY KEY (user_id, product_id) ); -- Query: Get user's cart SELECT * FROM shopping_carts WHERE user_id = ?; -- Query: Add to cart INSERT INTO shopping_carts (user_id, product_id, product_name, price, quantity, added_at) VALUES (?, ?, ?, ?, ?, toTimestamp(now())); -- Query: Update quantity UPDATE shopping_carts SET quantity = ? WHERE user_id = ? AND product_id = ?; -- Query: Remove from cart DELETE FROM shopping_carts WHERE user_id = ? AND product_id = ?;
5

Orders Table (by User)

-- Orders partitioned by user + month (time-bucketing) CREATE TABLE orders_by_user ( user_id UUID, order_month TEXT, -- '2024-01' (bucket) order_time TIMESTAMP, order_id UUID, total_amount DECIMAL, status TEXT, -- pending, shipped, delivered shipping_address TEXT, items LIST<FROZEN<order_item>>, PRIMARY KEY ((user_id, order_month), order_time, order_id) ) WITH CLUSTERING ORDER BY (order_time DESC, order_id ASC); -- UDT for order items CREATE TYPE order_item ( product_id UUID, product_name TEXT, price DECIMAL, quantity INT ); -- Query: Get recent orders SELECT * FROM orders_by_user WHERE user_id = ? AND order_month = '2024-01';
6

Orders by ID (Direct Lookup)

-- Order details by order ID (for tracking) CREATE TABLE orders_by_id ( order_id UUID PRIMARY KEY, user_id UUID, order_time TIMESTAMP, total_amount DECIMAL, status TEXT, shipping_address TEXT, tracking_number TEXT, items LIST<FROZEN<order_item>> ); -- Query: Track order SELECT * FROM orders_by_id WHERE order_id = ?;
7

Product Reviews Table

-- Reviews partitioned by product CREATE TABLE reviews_by_product ( product_id UUID, review_time TIMESTAMP, review_id UUID, user_id UUID, user_name TEXT, rating INT, -- 1-5 stars title TEXT, review_text TEXT, verified_purchase BOOLEAN, helpful_count COUNTER, PRIMARY KEY (product_id, review_time, review_id) ) WITH CLUSTERING ORDER BY (review_time DESC, review_id ASC); -- Query: Get product reviews SELECT * FROM reviews_by_product WHERE product_id = ? LIMIT 10;
8

User Profiles Table

-- User account information CREATE TABLE users ( user_id UUID PRIMARY KEY, email TEXT, full_name TEXT, phone TEXT, addresses LIST<FROZEN<address>>, created_at TIMESTAMP, last_login TIMESTAMP ); CREATE TYPE address ( address_id UUID, street TEXT, city TEXT, state TEXT, zip TEXT, country TEXT, is_default BOOLEAN );

๐Ÿ’ป Implementation

Python implementation!

Product Service

# product_service.py from cassandra.cluster import Cluster from decimal import Decimal import uuid class ProductService: def __init__(self, contact_points): cluster = Cluster(contact_points) self.session = cluster.connect('shopfast') # Prepared statements self.get_product = self.session.prepare(""" SELECT * FROM products_by_id WHERE product_id = ? """) self.browse_category = self.session.prepare(""" SELECT * FROM products_by_category WHERE category = ? LIMIT ? """) def get_product_details(self, product_id): """Get complete product information""" row = self.session.execute(self.get_product, (product_id,)).one() if row: return { 'product_id': row.product_id, 'name': row.name, 'description': row.description, 'brand': row.brand, 'category': row.category, 'price': float(row.price), 'discount_percent': float(row.discount_percent) if row.discount_percent else 0, 'image_urls': row.image_urls, 'attributes': row.attributes, 'inventory_count': row.inventory_count, 'rating_avg': float(row.rating_avg) if row.rating_avg else 0, 'rating_count': row.rating_count } return None def browse_category(self, category, limit=50, min_price=None, max_price=None): """Browse products by category with price filter""" if min_price and max_price: query = """ SELECT * FROM products_by_category WHERE category = ? AND price >= ? AND price <= ? LIMIT ? """ rows = self.session.execute( query, (category, Decimal(str(min_price)), Decimal(str(max_price)), limit) ) else: rows = self.session.execute(self.browse_category, (category, limit)) return [ { 'product_id': row.product_id, 'name': row.name, 'brand': row.brand, 'price': float(row.price), 'image_url': row.image_url, 'rating_avg': float(row.rating_avg) if row.rating_avg else 0, 'discount_percent': float(row.discount_percent) if row.discount_percent else 0 } for row in rows ] def check_inventory(self, product_id): """Check if product is in stock""" row = self.session.execute(self.get_product, (product_id,)).one() return row.inventory_count > 0 if row else False # Usage product_service = ProductService(['localhost']) # Get product product = product_service.get_product_details(product_id) print(f"{product['name']}: ${product['price']}") # Browse electronics under $500 products = product_service.browse_category( 'Electronics', min_price=100, max_price=500, limit=20 )

Shopping Cart Service

# cart_service.py from datetime import datetime class CartService: def __init__(self, session): self.session = session self.add_item = session.prepare(""" INSERT INTO shopping_carts (user_id, product_id, product_name, price, quantity, image_url, added_at) VALUES (?, ?, ?, ?, ?, ?, ?) """) self.update_quantity = session.prepare(""" UPDATE shopping_carts SET quantity = ? WHERE user_id = ? AND product_id = ? """) self.remove_item = session.prepare(""" DELETE FROM shopping_carts WHERE user_id = ? AND product_id = ? """) def add_to_cart(self, user_id, product_id, product_name, price, quantity, image_url): """Add item to cart""" self.session.execute( self.add_item, (user_id, product_id, product_name, Decimal(str(price)), quantity, image_url, datetime.now()) ) def update_item_quantity(self, user_id, product_id, quantity): """Update quantity of item in cart""" if quantity <= 0: self.remove_from_cart(user_id, product_id) else: self.session.execute(self.update_quantity, (quantity, user_id, product_id)) def remove_from_cart(self, user_id, product_id): """Remove item from cart""" self.session.execute(self.remove_item, (user_id, product_id)) def get_cart(self, user_id): """Get all items in user's cart""" query = "SELECT * FROM shopping_carts WHERE user_id = ?" rows = self.session.execute(query, (user_id,)) items = [] total = 0 for row in rows: item_total = float(row.price) * row.quantity total += item_total items.append({ 'product_id': row.product_id, 'product_name': row.product_name, 'price': float(row.price), 'quantity': row.quantity, 'image_url': row.image_url, 'item_total': item_total }) return { 'items': items, 'total_amount': total, 'item_count': len(items) } def clear_cart(self, user_id): """Clear entire cart (after checkout)""" query = "DELETE FROM shopping_carts WHERE user_id = ?" self.session.execute(query, (user_id,)) # Usage cart_service = CartService(session) # Add to cart cart_service.add_to_cart( user_id=user_id, product_id=product_id, product_name="Wireless Headphones", price=99.99, quantity=1, image_url="https://..." ) # Get cart cart = cart_service.get_cart(user_id) print(f"Cart total: ${cart['total_amount']:.2f}")

๐Ÿ›’ Cart & Orders Flow

Checkout process!

Order Service

# order_service.py from datetime import datetime import uuid class OrderService: def __init__(self, session): self.session = session def create_order(self, user_id, cart_items, shipping_address): """Create order from cart""" order_id = uuid.uuid4() order_time = datetime.now() order_month = order_time.strftime('%Y-%m') # Calculate total total_amount = sum(item['price'] * item['quantity'] for item in cart_items) # Convert cart items to order items order_items = [ { 'product_id': item['product_id'], 'product_name': item['product_name'], 'price': Decimal(str(item['price'])), 'quantity': item['quantity'] } for item in cart_items ] # Insert into orders_by_user self.session.execute(""" INSERT INTO orders_by_user (user_id, order_month, order_time, order_id, total_amount, status, shipping_address, items) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, (user_id, order_month, order_time, order_id, Decimal(str(total_amount)), 'pending', shipping_address, order_items)) # Insert into orders_by_id (for tracking) self.session.execute(""" INSERT INTO orders_by_id (order_id, user_id, order_time, total_amount, status, shipping_address, items) VALUES (?, ?, ?, ?, ?, ?, ?) """, (order_id, user_id, order_time, Decimal(str(total_amount)), 'pending', shipping_address, order_items)) return { 'order_id': order_id, 'order_time': order_time, 'total_amount': total_amount } def get_order_history(self, user_id, month=None): """Get user's order history""" if not month: month = datetime.now().strftime('%Y-%m') query = """ SELECT * FROM orders_by_user WHERE user_id = ? AND order_month = ? """ rows = self.session.execute(query, (user_id, month)) return [ { 'order_id': row.order_id, 'order_time': row.order_time, 'total_amount': float(row.total_amount), 'status': row.status, 'item_count': len(row.items) } for row in rows ] def track_order(self, order_id): """Track order status""" query = "SELECT * FROM orders_by_id WHERE order_id = ?" row = self.session.execute(query, (order_id,)).one() if row: return { 'order_id': row.order_id, 'status': row.status, 'tracking_number': row.tracking_number, 'order_time': row.order_time, 'total_amount': float(row.total_amount) } return None # Complete checkout flow def checkout(user_id, shipping_address): # 1. Get cart cart = cart_service.get_cart(user_id) if not cart['items']: return {'error': 'Cart is empty'} # 2. Create order order = order_service.create_order( user_id, cart['items'], shipping_address ) # 3. Clear cart cart_service.clear_cart(user_id) # 4. Update inventory (separate service) # inventory_service.decrease_stock(cart['items']) return order

โšก Performance Optimization

Production optimization!

๐Ÿ’พ

Caching Strategy

  • Redis cache: Product details (5-min TTL)
  • CDN: Product images & static data
  • Application cache: Category listings
  • Cache invalidation: On price/inventory updates
  • Result: 90%+ cache hit rate
๐Ÿ”

Search Optimization

  • Elasticsearch: Product search
  • Sync pipeline: Cassandra โ†’ ES
  • Faceted search: Brand, price, ratings
  • Autocomplete: Suggest as you type
  • Response time: <100ms for searches
๐Ÿ“Š

Query Optimization

  • Denormalization: Duplicate data across tables
  • Prepared statements: All queries
  • Batch operations: Checkout process
  • Async writes: Non-critical updates
  • Read consistency: ONE for speed
๐Ÿ“ˆ

Scalability

  • Time-bucketing: Orders by month
  • Partition size: <100MB per partition
  • Black Friday prep: Add nodes in advance
  • Auto-scaling: Based on metrics
  • Linear growth: 2x nodes = 2x capacity

Anti-Patterns to Avoid

  • โŒ Don't: Use ALLOW FILTERING in production
  • โŒ Don't: Store large images in Cassandra (use S3/CDN)
  • โŒ Don't: Create unbounded partitions (use time-bucketing)
  • โŒ Don't: Use SELECT * on large tables
  • โŒ Don't: Perform JOINs client-side at scale
  • โœ… Do: Denormalize data for read efficiency
  • โœ… Do: Use separate tables per query pattern

๐Ÿš€ Deployment Architecture

Production deployment!

Multi-Region E-Commerce Architecture

                  Global Load Balancer
                          โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ”‚                โ”‚                โ”‚
         โ–ผ                โ–ผ                โ–ผ
    US-East          US-West          EU-West
    Region           Region           Region
         โ”‚                โ”‚                โ”‚
    โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”
    โ”‚         โ”‚      โ”‚         โ”‚      โ”‚         โ”‚
    โ–ผ         โ–ผ      โ–ผ         โ–ผ      โ–ผ         โ–ผ
  Redis    Cassandra Redis  Cassandra Redis  Cassandra
  Cache    (6 nodes) Cache  (6 nodes) Cache  (6 nodes)
    โ”‚         โ”‚        โ”‚       โ”‚        โ”‚        โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
              โ”‚                โ”‚
              โ–ผ                โ–ผ
      Elasticsearch      S3 (Images)
      (Product Search)   (CDN CloudFront)
        

Production Checklist

Component Configuration Status
Cluster Size 18 nodes (6 per region) โœ…
Replication RF=3 per region (9 total) โœ…
Write Throughput 100K writes/second (peak) โœ…
Read Latency p99 < 10ms โœ…
Caching Redis + CDN (90% hit rate) โœ…
Search Elasticsearch cluster โœ…
Monitoring Datadog + PagerDuty โœ…
Disaster Recovery Cross-region replication โœ…

๐ŸŽ‰ Project Complete!

You built a production-ready e-commerce platform at Amazon scale!

๐ŸŽ“ What You Built:

  • ๐Ÿ›๏ธ Scale: 100M products, 50M users, 27M orders/day (peak)
  • ๐Ÿ—บ๏ธ Data model: 8 tables covering all use cases
  • ๐Ÿ“‹ Schema: Products, cart, orders, reviews, users
  • ๐Ÿ’ป Implementation: Product, cart, order services
  • ๐Ÿ›’ Shopping flow: Browse โ†’ Cart โ†’ Checkout โ†’ Orders
  • โšก Optimization: Redis cache, ES search, denormalization
  • ๐Ÿš€ Deployment: Multi-region with 18 nodes

๐Ÿ’ก Key Learnings:

  1. Denormalization: Duplicate data for read efficiency
  2. Query-driven design: One table per access pattern
  3. Shopping cart: Simple partition by user_id
  4. Time-bucketing: Orders by user + month
  5. Separate lookup tables: orders_by_id for tracking
  6. Caching strategy: Redis + CDN for 90% hit rate
  7. Search integration: Elasticsearch for product search

๐Ÿ›’ Architecture Highlights:

  • โœ… 8 tables: products_by_id, by_category, cart, orders, reviews
  • โœ… Denormalized: Product data duplicated for performance
  • โœ… Write path: 100K cart updates/second
  • โœ… Read path: Sub-10ms with caching
  • โœ… Global: 3 regions, 18 nodes, RF=9
  • โœ… Zero downtime: Even during Black Friday

๐Ÿš€ Next Steps:

  • ๐Ÿ“Š Add analytics (product views, conversion rates)
  • ๐Ÿค– Implement recommendation engine (ML)
  • ๐Ÿ’ณ Add payment gateway integration
  • ๐Ÿ“ง Build email notification system
  • ๐Ÿ“ฑ Create mobile app (iOS/Android)
  • ๐ŸŒ Expand to more regions

Congratulations on completing this advanced Cassandra e-commerce project! ๐ŸŽ‰

font-weight: 700;"> ๐ŸŽฏ You're ready to build e-commerce at scale! ๐Ÿ›’
Ship it to production!

Advertisement

Responsive Ad