Design a system like Amazon - System design interview
Designing a system like Amazon involves creating a highly scalable e-commerce platform that can handle millions of products, transactions, user interactions, and logistics operations. Below is a detailed system design using Prisma for database modeling, Express.js for API routes, and a recommended tech stack:
Tech Stack
- Backend: Node.js with Express.js
- Database: PostgreSQL for relational data (users, orders, products), Elasticsearch for search indexing
- ORM: Prisma for database interactions
- Caching: Redis for caching frequently accessed data (product details, user sessions)
- Storage: Amazon S3 for product images and media
- Message Broker: RabbitMQ for managing asynchronous tasks and order processing
- Authentication: OAuth for user authentication
- Monitoring: Prometheus and Grafana for metrics monitoring
System Components
-
Client Applications (Web, Mobile, Desktop):
- Various clients for browsing products, placing orders, managing accounts, etc.
-
Express.js Backend
-
Prisma Models:
// schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) username String @unique email String? @unique password String orders Order[] cart Cart? } model Product { id Int @id @default(autoincrement()) name String description String? price Float imageUrl String? category String inventory Int } model Order { id Int @id @default(autoincrement()) userId Int user User @relation(fields: [userId], references: [id]) products Product[] totalPrice Float status String // pending, shipped, delivered, cancelled, etc. createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Cart { id Int @id @default(autoincrement()) userId Int user User @relation(fields: [userId], references: [id]) products Product[] @relation("CartProducts", references: [id]) }
-
Express API Routes:
// server.js const express = require('express'); const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient(); const app = express(); app.use(express.json()); // Endpoint for fetching all products app.get('/products', async (req, res) => { try { const products = await prisma.product.findMany(); res.json(products); } catch (error) { console.error(error); res.status(500).json({ error: 'Failed to fetch products' }); } }); // Endpoint for creating a new order app.post('/orders', async (req, res) => { const { userId, productIds } = req.body; try { // Fetch products from IDs const products = await prisma.product.findMany({ where: { id: { in: productIds }, }, }); // Calculate total price const totalPrice = products.reduce((acc, curr) => acc + curr.price, 0); // Create order const order = await prisma.order.create({ data: { userId: parseInt(userId), products: { connect: productIds.map(id => ({ id: parseInt(id) })) }, totalPrice, status: 'pending', }, }); res.json(order); } catch (error) { console.error(error); res.status(500).json({ error: 'Failed to create order' }); } }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); });
-
-
Database Layer
- PostgreSQL for user data (profiles, orders), product details, and relational data.
- Elasticsearch for product search indexing and fast retrieval.
-
Caching
- Redis: Caches frequently accessed data such as product details and user sessions to improve response times.
-
Message Broker
- RabbitMQ: Manages asynchronous tasks such as order processing, email notifications, and inventory updates.
-
Storage
- Amazon S3: Stores product images and media securely with high availability and durability.
-
Authentication
- OAuth: Used for user authentication and authorization to access Amazon services securely.
-
Monitoring and Analytics
- Prometheus and Grafana: Monitor system health, performance metrics, and usage statistics to optimize performance and troubleshoot issues.
Scalability and Fault Tolerance
- Horizontal Scaling: Deploy multiple instances of microservices and use load balancers to handle increased traffic.
- Database Sharding: Partition databases to distribute load and improve scalability.
- Redundancy and Backup: Deploy services across multiple availability zones (AZs) for fault tolerance and ensure regular backups for data integrity and disaster recovery.
Security
- Encryption: Use SSL/TLS for data encryption in transit to protect user information and communications.
Published on: Jul 10, 2024, 01:12 AM