Location: shared/sharding/
- Defines 3 PostgreSQL shards with environment URLs
- Maps regions to shards for automatic routing
- Shards cover US, Canada, and Mexico regions
- Easy to add more shards by extending configuration
getShardByRegion(city): Routes by city name (case-insensitive, fuzzy match)getShardById(shardId): Direct shard accessdetermineUserShard(userId, city): User-specific routingdetermineOrderShard(orderId, city): Order-specific routinggetShardByHash(key): Consistent hash-based fallback
Usage Pattern:
const shard = getShardByRegion('san-francisco');
const prisma = getPrismaClient('san-francisco');
await prisma.user.findMany();Features:
- HTTP forwarding to microservices
- Rate limiting middleware (10 req/s general, 5 req/s auth, 20 req/s orders)
- Request logging
- Error handling
- Shard-aware routing ready
Routes:
POST /auth/*→ Auth Service (3001)GET/POST /orders/*→ Order Service (3002)GET/POST /restaurants/*→ Restaurant Service (3003)GET/POST/PATCH /delivery/*→ Delivery Service (3004)
Features:
- User registration with role-based access
- JWT token generation (default: 24h expiry)
- Bcrypt password hashing
- Token refresh endpoint
- Shard-aware user storage
Endpoints:
POST /register- Create user accountPOST /login- Get JWT tokenPOST /refresh- Refresh expired token
Database: PostgreSQL (sharded by user city)
Sample Registration:
POST /register
{
"email": "user@example.com",
"password": "secure123",
"firstName": "John",
"lastName": "Doe",
"phoneNumber": "+1234567890",
"role": "customer",
"city": "san-francisco"
}Features:
- Create, read, update orders
- RabbitMQ event publishing
- Shard-aware storage
Endpoints:
POST /- Create order (publishesorder.createdevent)GET /:id- Get order details (requires?city=...)GET /- List customer orders (requires?customerId=...&city=...)PATCH /:id/status- Update order status
RabbitMQ Events Published:
// order.created event
{
eventType: 'order.created',
orderId: 'uuid',
customerId: 'uuid',
restaurantId: 'uuid',
deliveryCity: 'San Francisco',
totalAmount: 45.99,
estimatedDeliveryTime: 30,
timestamp: new Date()
}Database: PostgreSQL (sharded by order city)
Features:
- MongoDB for restaurant metadata
- Mongoose schemas for type safety
- Search and filtering
Models:
Restaurant: Stores restaurant info, owner, ratingsMenuItem: Menu items with pricing and categories
Endpoints:
GET /- List restaurants (with filtering by city)GET /:id- Get restaurant detailsGET /:id/menu- Get menu itemsPOST /- Create restaurant
Database: MongoDB (non-sharded, centralized)
Features:
- RabbitMQ event consumer for order assignments
- Delivery partner availability management
- Location update handling
- Automatic order assignment
Event Consumers:
order.created- Finds available delivery partner and assignsorder.assigned- Ready for pickup
Endpoints:
GET /assignments- Get current delivery assignmentPATCH /:id/location- Update rider GPS coordinatesPOST /:id/accept- Accept delivery order
Database: PostgreSQL (sharded by delivery city)
Sample Location Update:
PATCH /delivery/partner123/location
{
"latitude": 37.7749,
"longitude": -122.4194,
"city": "San Francisco"
}Features:
- Socket.IO WebSocket server
- Real-time location broadcasting
- Redis-backed location storage
- Efficient pub/sub pattern
Socket.IO Events:
Client → Server:
subscribe-order:{ orderId: string }rider-location-update:{ orderId, deliveryPartnerId, latitude, longitude }get-location:(orderId, callback)unsubscribe-order:{ orderId: string }
Server → Client:
location-updated:{ orderId, deliveryPartnerId, latitude, longitude, timestamp }error:{ message: string }
Usage Example:
const socket = io('http://localhost:3005');
// Subscribe to order
socket.emit('subscribe-order', 'order-uuid');
// Listen for updates
socket.on('location-updated', (data) => {
console.log(`Rider at ${data.latitude}, ${data.longitude}`);
});
// Get current location
socket.emit('get-location', 'order-uuid', (response) => {
console.log(response.data);
});Database: Redis (in-memory, with 1-hour TTL)
Tech Stack:
- React 18 with TypeScript
- Vite for fast bundling
- Tailwind CSS for styling
- Socket.IO client for real-time updates
- Axios for HTTP requests
- Context API for state management
Pages:
LoginPage: Authentication UIHomePage: Main dashboard (orders & restaurants tabs)TrackingPage: Real-time order tracking
Context:
AuthContext: Manages user state and JWT token
Utils:
apiClient.ts: Configured Axios instance with auth interceptorsocketClient.ts: Socket.IO initialization and event handlers
┌─────────┐ ┌─────┐
│Customer │ Order │Order│
│App ├────────►│Svc │
└─────────┘ └─────┘
│
Publish
│
order.created
│
▼
┌─────────┐
│RabbitMQ │
└────┬────┘
│
Consume
│
▼
┌──────────┐
│Delivery │
│Svc │
└────┬─────┘
│
Find available
delivery partner
│
▼
┌────────────┐
│Update DB │
│Assign Order│
└────────────┘
│
Publish order.assigned
│
▼
┌─────────┐
│Customer │
│WebSocket│
│Receives │
│Update │
└─────────┘
CREATE TABLE "User" (
id VARCHAR(36) PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
firstName VARCHAR(255),
lastName VARCHAR(255),
phoneNumber VARCHAR(20),
role VARCHAR(50),
city VARCHAR(100),
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE "Order" (
id VARCHAR(36) PRIMARY KEY,
customerId VARCHAR(36),
restaurantId VARCHAR(36),
deliveryPartnerId VARCHAR(36),
status VARCHAR(50),
totalAmount DECIMAL(10, 2),
deliveryAddress TEXT,
city VARCHAR(100),
latitude DECIMAL(9, 6),
longitude DECIMAL(9, 6),
estimatedDeliveryTime INT,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE "DeliveryPartner" (
id VARCHAR(36) PRIMARY KEY,
userId VARCHAR(36),
city VARCHAR(100),
latitude DECIMAL(9, 6),
longitude DECIMAL(9, 6),
isAvailable BOOLEAN DEFAULT TRUE,
currentOrderId VARCHAR(36),
totalDeliveries INT DEFAULT 0,
rating DECIMAL(3, 2),
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);{
_id: ObjectId,
name: String,
city: String,
address: String,
latitude: Number,
longitude: Number,
phoneNumber: String,
email: String,
ownerUserId: String,
rating: Number,
isActive: Boolean,
createdAt: Date,
updatedAt: Date
}{
_id: ObjectId,
restaurantId: String,
name: String,
description: String,
price: Number,
category: String,
isAvailable: Boolean,
createdAt: Date,
updatedAt: Date
}NODE_ENV=development
# Database URLs
POSTGRES_SHARD_A_URL=postgresql://postgres:postgres@postgres-shard-a:5432/shard_a
POSTGRES_SHARD_B_URL=postgresql://postgres:postgres@postgres-shard-b:5432/shard_b
POSTGRES_SHARD_C_URL=postgresql://postgres:postgres@postgres-shard-c:5432/shard_c
MONGODB_URL=mongodb://root:mongodb@mongodb:27017/restaurants?authSource=admin
REDIS_URL=redis://redis:6379
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
# Service Ports
API_GATEWAY_PORT=3000
AUTH_SERVICE_PORT=3001
ORDER_SERVICE_PORT=3002
RESTAURANT_SERVICE_PORT=3003
DELIVERY_SERVICE_PORT=3004
TRACKING_SERVICE_PORT=3005
# JWT
JWT_SECRET=your-secret-key-change-in-production
JWT_EXPIRY=24h
# Shard Configuration
SHARD_A_REGIONS=us-west,ca
SHARD_B_REGIONS=us-east,us-central
SHARD_C_REGIONS=us-south,mx
VITE_API_URL=http://localhost:3000
VITE_TRACKING_URL=http://localhost:3005
- Restaurant data: Cache in Redis for 1 hour
- User profiles: Cache in Redis for 30 minutes
- Delivery partner availability: Real-time from DB
- General: 10 req/s per IP
- Auth: 5 req/s per IP
- Orders: 20 req/s per IP
- Create indexes on frequently queried columns
- Use connection pooling
- Implement query caching at application level
- Connection pooling
- Rooms for order-specific updates
- Message compression
- ✅ Use environment variables for secrets
- ⏳ Implement CORS properly (not
*) - ⏳ Add request validation middleware
- ⏳ Implement API key authentication for services
- ⏳ Use HTTPS for all connections
- ⏳ Add rate limiting per user/API key
- ⏳ Implement audit logging
- ⏳ Add database encryption
- ⏳ Implement circuit breakers for service calls
- ⏳ Add monitoring and alerting
- Service layer functions
- Utility functions
- Event handlers
- Service-to-service communication
- Database operations
- RabbitMQ messaging
- Complete order flow
- WebSocket connections
- Authentication flow
- Add more instances of stateless services
- Use load balancer to distribute requests
- Ensure database connection pooling
- Increase service memory/CPU limits
- Optimize database queries
- Implement caching strategies
- Current: 3-way application-level sharding
- Future: Add more shards as regions grow
- Use read replicas for read-heavy workloads
- Update
.envwith production values - Change
JWT_SECRETto strong key - Enable HTTPS in Nginx config
- Set up monitoring/logging
- Configure database backups
- Set up CI/CD pipeline
- Load test the system
- Set up health checks
- Configure auto-scaling
- Document API endpoints
- Set up error tracking (Sentry, etc.)
- Configure CDN for static assets
- Add payment processing (Stripe/PayPal)
- Implement push notifications
- Add recommendation engine
- Implement loyalty program
- Add multi-language support
- Implement rating/review system
- Add chat between customers and support
- Implement promotions/discounts
- Add analytics dashboard
- Implement machine learning for route optimization