# Horizontal Scaling Operations Guide **Audience**: DevOps Engineers, System Administrators **Last Updated**: November 2025 **Applies To**: MapleFile Backend --- ## Table of Contents 1. [Overview](#overview) 2. [Understanding Scaling](#understanding-scaling) 3. [Prerequisites](#prerequisites) 4. [Scaling Up (Adding Replicas)](#scaling-up-adding-replicas) 5. [Scaling Down (Removing Replicas)](#scaling-down-removing-replicas) 6. [Adding Worker Nodes](#adding-worker-nodes) 7. [Monitoring Scaled Services](#monitoring-scaled-services) 8. [Common Scenarios](#common-scenarios) 9. [Troubleshooting](#troubleshooting) 10. [Best Practices](#best-practices) --- ## Overview ### What is Horizontal Scaling? **Horizontal scaling** means adding more servers (replicas) to handle increased load, rather than making existing servers more powerful (vertical scaling). **Example:** - **Before:** 1 server handling 100 requests/second - **After:** 3 servers each handling 33 requests/second ### Why Scale Horizontally? - **Higher availability**: If one server fails, others keep serving traffic - **Better performance**: Load distributed across multiple servers - **Handle traffic spikes**: Scale up during peak times, scale down during quiet times - **Zero downtime deployments**: Update servers one at a time ### Current Architecture **Single-Server Setup (Current):** ``` Worker-8: Backend (1 replica) + Cassandra + Redis ↓ 100% of traffic ``` **Multi-Server Setup (After Scaling):** ``` Worker-8: Backend (replica 1) + Cassandra + Redis Worker-10: Backend (replica 2) Worker-11: Backend (replica 3) ↓ ↓ ↓ 33% 33% 34% of traffic ``` --- ## Understanding Scaling ### Vertical vs Horizontal Scaling | Aspect | Vertical Scaling | Horizontal Scaling | |--------|-----------------|-------------------| | **Method** | Bigger server | More servers | | **Cost** | Expensive (high-tier droplets) | Cheaper (many small droplets) | | **Limit** | Hardware limit (max CPU/RAM) | Unlimited (add more servers) | | **Downtime** | Required (resize server) | Zero downtime | | **Complexity** | Simple | More complex (load balancing) | | **Failure** | Single point of failure | High availability | **Example:** - **Vertical**: Upgrade from $12/mo (2 vCPU, 2GB RAM) to $48/mo (8 vCPU, 16GB RAM) - **Horizontal**: Add 3x $12/mo droplets = $36/mo total for 6 vCPU, 6GB RAM ### When to Scale **Scale up when:** - CPU usage consistently above 70% - Memory usage consistently above 80% - Response times increasing - Error rates increasing - Traffic growing steadily **Scale down when:** - CPU usage consistently below 30% - Memory usage consistently below 50% - Traffic decreased - Cost optimization needed ### How Docker Swarm Handles Scaling Docker Swarm automatically: - **Load balances** traffic across all replicas - **Health checks** each replica - **Restarts** failed replicas - **Distributes** replicas across worker nodes - **Updates** replicas with zero downtime --- ## Prerequisites ### Before Scaling Up Ensure your application supports horizontal scaling: #### ✅ **MapleFile Backend is Ready** MapleFile backend is designed for horizontal scaling: - ✅ **Stateless**: No local state (uses Cassandra/Redis for shared state) - ✅ **Leader election**: Scheduled tasks run only on one instance - ✅ **Shared database**: All replicas use same Cassandra cluster - ✅ **Shared cache**: All replicas use same Redis instance - ✅ **Session storage**: JWT tokens are stateless (no session store needed) #### ⚠️ **Check Your Application** If you were scaling a different app, verify: - [ ] No local file storage (use S3 instead) - [ ] No in-memory sessions (use Redis instead) - [ ] No local caching (use Redis instead) - [ ] Database supports concurrent connections - [ ] No port conflicts (don't bind to host ports) --- ## Scaling Up (Adding Replicas) ### Method 1: Quick Scale (Same Worker) **Scale to multiple replicas on the same worker node.** #### Step 1: SSH to Manager ```bash ssh dockeradmin@ ``` #### Step 2: Scale the Service ```bash # Scale MapleFile backend from 1 to 3 replicas docker service scale maplefile_backend=3 # Or use update command docker service update --replicas 3 maplefile_backend ``` #### Step 3: Monitor Scaling ```bash # Watch replicas start watch docker service ls # Expected output: # NAME REPLICAS IMAGE # maplefile_backend 3/3 ...maplefile-backend:prod ``` **3/3 means:** 3 desired replicas, 3 running #### Step 4: Verify All Replicas Running ```bash # Check where replicas are running docker service ps maplefile_backend # Output: # NAME NODE CURRENT STATE # maplefile_backend.1 worker-8 Running 5 minutes ago # maplefile_backend.2 worker-8 Running 30 seconds ago # maplefile_backend.3 worker-8 Running 30 seconds ago ``` #### Step 5: Check Logs ```bash # Check logs from all replicas docker service logs maplefile_backend --tail 50 # Look for successful startup from each replica ``` #### Step 6: Test Load Balancing ```bash # Make multiple requests - should be distributed across replicas for i in {1..10}; do curl -s https://maplefile.ca/health done # Check logs to see different replicas handling requests docker service logs maplefile_backend --tail 20 ``` ### Method 2: Scale Across Multiple Workers **Scale replicas across different worker nodes for better availability.** #### Step 1: Add Worker Nodes (If Needed) See [Adding Worker Nodes](#adding-worker-nodes) section below. #### Step 2: Label Worker Nodes ```bash # Label worker-10 as backend node docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-10-prod # Label worker-11 as backend node docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-11-prod # Verify labels docker node inspect mapleopentech-swarm-worker-10-prod --format '{{.Spec.Labels}}' ``` #### Step 3: Update Stack File ```bash # Edit stack file nano ~/stacks/maplefile-stack.yml ``` **Change deployment configuration:** ```yaml services: backend: deploy: replicas: 3 # Change from 1 to 3 placement: constraints: # Remove single-node constraint - node.labels.maplefile-backend == true # Now matches multiple workers preferences: # Spread replicas across different nodes - spread: node.hostname ``` #### Step 4: Redeploy Stack ```bash cd ~/stacks docker stack deploy -c maplefile-stack.yml maplefile ``` #### Step 5: Verify Distribution ```bash # Check which nodes replicas are running on docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}" # Expected output (distributed across nodes): # NAME NODE CURRENT STATE # maplefile_backend.1 worker-8 Running # maplefile_backend.2 worker-10 Running # maplefile_backend.3 worker-11 Running ``` ### Method 3: Auto-Scaling (Advanced) **Note:** Docker Swarm doesn't have built-in auto-scaling. You would need to implement custom auto-scaling using: - Prometheus for metrics - Custom script to monitor CPU/memory - Script to scale service based on thresholds **Example auto-scale script:** ```bash #!/bin/bash # auto-scale.sh - Example only, not production-ready # Get average CPU usage across all replicas CPU_AVG=$(docker stats --no-stream --format "{{.CPUPerc}}" | grep maplefile | awk '{sum+=$1; count++} END {print sum/count}') # Scale up if CPU > 70% if (( $(echo "$CPU_AVG > 70" | bc -l) )); then CURRENT=$(docker service inspect maplefile_backend --format '{{.Spec.Mode.Replicated.Replicas}}') NEW=$((CURRENT + 1)) docker service scale maplefile_backend=$NEW echo "Scaled up to $NEW replicas (CPU: $CPU_AVG%)" fi # Scale down if CPU < 30% and more than 1 replica if (( $(echo "$CPU_AVG < 30" | bc -l) )); then CURRENT=$(docker service inspect maplefile_backend --format '{{.Spec.Mode.Replicated.Replicas}}') if [ $CURRENT -gt 1 ]; then NEW=$((CURRENT - 1)) docker service scale maplefile_backend=$NEW echo "Scaled down to $NEW replicas (CPU: $CPU_AVG%)" fi fi ``` --- ## Scaling Down (Removing Replicas) ### When to Scale Down Scale down to save costs when: - Traffic decreased - CPU/memory usage consistently low - Cost optimization needed - Testing showed fewer replicas handle load fine ### Step 1: SSH to Manager ```bash ssh dockeradmin@ ``` ### Step 2: Scale Down Service ```bash # Scale from 3 replicas to 1 docker service scale maplefile_backend=1 # Or update docker service update --replicas 1 maplefile_backend ``` ### Step 3: Monitor Scaling Down ```bash # Watch replicas stop watch docker service ls # Expected output: # NAME REPLICAS IMAGE # maplefile_backend 1/1 ...maplefile-backend:prod ``` ### Step 4: Verify Which Replica Kept ```bash # Check which replica is still running docker service ps maplefile_backend # Output: # NAME NODE CURRENT STATE # maplefile_backend.1 worker-8 Running 10 minutes ago # maplefile_backend.2 worker-10 Shutdown 10 seconds ago # maplefile_backend.3 worker-11 Shutdown 10 seconds ago ``` ### Step 5: Test Service Still Works ```bash # Test endpoint curl https://maplefile.ca/health # Check logs docker service logs maplefile_backend --tail 20 ``` --- ## Adding Worker Nodes ### When to Add Worker Nodes Add worker nodes when: - Want to distribute backend across multiple servers - Current worker at capacity - Need better high availability - Planning for growth ### Step 1: Create New DigitalOcean Droplet **From DigitalOcean dashboard or CLI:** ```bash # Create worker-10 droplet (Ubuntu 22.04, $12/mo) doctl compute droplet create mapleopentech-swarm-worker-10-prod \ --region nyc3 \ --size s-2vcpu-2gb \ --image ubuntu-22-04-x64 \ --ssh-keys \ --tag-names production,swarm-worker,maplefile # Get IP address doctl compute droplet get mapleopentech-swarm-worker-10-prod --format PublicIPv4 ``` ### Step 2: Install Docker on New Worker ```bash # SSH to new worker ssh root@ # Install Docker curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh # Verify Docker installed docker --version ``` ### Step 3: Join Worker to Swarm **On manager node:** ```bash # Get join token ssh dockeradmin@ docker swarm join-token worker # Output: # docker swarm join --token SWMTKN-xxx :2377 ``` **On new worker:** ```bash # Join swarm (use token from above) docker swarm join --token SWMTKN-xxx :2377 # Output: # This node joined a swarm as a worker. ``` ### Step 4: Verify Worker Joined **On manager:** ```bash # List all nodes docker node ls # Output should include new worker: # ID HOSTNAME STATUS AVAILABILITY # xyz123 mapleopentech-swarm-manager-1-prod Ready Active Leader # abc456 mapleopentech-swarm-worker-8-prod Ready Active # def789 mapleopentech-swarm-worker-10-prod Ready Active ← New! ``` ### Step 5: Label New Worker ```bash # Label worker-10 for backend workloads docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-10-prod # Verify label docker node inspect mapleopentech-swarm-worker-10-prod --format '{{.Spec.Labels}}' ``` ### Step 6: Join to Private Network **Important:** Workers must access Cassandra and Redis. ```bash # Add worker-10 to mapleopentech-private-prod network # This is done automatically when services start on the worker # But verify connectivity: # On worker-10, test Redis connectivity ssh root@ docker run --rm --network mapleopentech-private-prod redis:7.0-alpine redis-cli -h redis ping # Should output: PONG ``` ### Step 7: Scale Service to Use New Worker ```bash # On manager docker service update --replicas 2 maplefile_backend # Check distribution docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}" # Should show replicas on both worker-8 and worker-10 ``` --- ## Monitoring Scaled Services ### Real-Time Monitoring **Watch service status:** ```bash # All services watch docker service ls # Specific service watch 'docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}"' ``` **Monitor resource usage:** ```bash # CPU and memory of all replicas docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile # Continuous monitoring docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile ``` ### Check Load Distribution **See which replica handled request:** ```bash # Follow logs from all replicas docker service logs -f maplefile_backend # Filter for specific endpoint docker service logs -f maplefile_backend | grep "/api/v1/users" # You should see different replica IDs in logs ``` ### Prometheus Monitoring (If Configured) **Query metrics:** ```promql # Average CPU usage across all replicas avg(rate(container_cpu_usage_seconds_total{service="maplefile_backend"}[5m])) # Request rate per replica sum(rate(http_requests_total{service="maplefile_backend"}[5m])) by (instance) # P95 response time histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) ``` --- ## Common Scenarios ### Scenario 1: Handling Traffic Spike **Sudden traffic increase - need to scale quickly.** ```bash # SSH to manager ssh dockeradmin@ # Check current load docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile # Scale from 1 to 5 replicas immediately docker service scale maplefile_backend=5 # Monitor scaling watch docker service ls # Wait for all replicas healthy (5/5) # Verify load distributed docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile # After traffic spike ends, scale back down docker service scale maplefile_backend=2 ``` ### Scenario 2: Planned Scaling for Event **You know a marketing campaign will increase traffic.** **Day Before Event:** ```bash # Add worker nodes if needed (see Adding Worker Nodes section) # Scale up gradually docker service scale maplefile_backend=3 # Verify all healthy docker service ps maplefile_backend # Load test # Run load tests to verify system handles expected traffic ``` **During Event:** ```bash # Monitor continuously watch docker service ls # Scale up more if needed docker service scale maplefile_backend=5 # Check logs for errors docker service logs maplefile_backend --tail 100 | grep -i error ``` **After Event:** ```bash # Scale back down gradually docker service scale maplefile_backend=3 # Monitor for 1 hour # Scale to normal docker service scale maplefile_backend=1 ``` ### Scenario 3: Zero-Downtime Deployment with Scaling **Deploy new version with zero downtime using scaled replicas.** ```bash # 1. Scale up to 3 replicas BEFORE deploying docker service scale maplefile_backend=3 # Wait for all healthy docker service ps maplefile_backend # 2. Deploy new image docker service update --image registry.digitalocean.com/ssp/maplefile-backend:prod maplefile_backend # Docker Swarm will: # - Update replica 1, wait for health check # - Update replica 2, wait for health check # - Update replica 3, wait for health check # Always at least 2 replicas serving traffic # 3. Monitor update docker service ps maplefile_backend # 4. After successful deployment, scale back down if desired docker service scale maplefile_backend=1 ``` ### Scenario 4: High Availability Setup **Run 3 replicas across 3 workers for maximum availability.** ```bash # Ensure 3 worker nodes labeled docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-8-prod docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-10-prod docker node update --label-add maplefile-backend=true mapleopentech-swarm-worker-11-prod # Update stack file for HA nano ~/stacks/maplefile-stack.yml ``` **Stack file HA configuration:** ```yaml services: backend: deploy: replicas: 3 placement: constraints: - node.labels.maplefile-backend == true preferences: # Spread across different nodes - spread: node.hostname max_replicas_per_node: 1 # Only 1 replica per node update_config: parallelism: 1 # Update 1 replica at a time delay: 10s failure_action: rollback monitor: 60s order: start-first # Start new before stopping old ``` **Deploy HA stack:** ```bash docker stack deploy -c maplefile-stack.yml maplefile # Verify distribution docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}" # Should show 1 replica on each worker ``` ### Scenario 5: Cost Optimization **Running 3 replicas but only need 1 during off-peak hours.** **Create scale-down script:** ```bash # Create script cat > ~/stacks/scale-schedule.sh << 'EOF' #!/bin/bash HOUR=$(date +%H) # Scale up during business hours (9 AM - 6 PM) if [ $HOUR -ge 9 ] && [ $HOUR -lt 18 ]; then docker service scale maplefile_backend=3 echo "$(date): Scaled to 3 replicas (business hours)" # Scale down during off-peak (6 PM - 9 AM) else docker service scale maplefile_backend=1 echo "$(date): Scaled to 1 replica (off-peak)" fi EOF chmod +x ~/stacks/scale-schedule.sh ``` **Add to crontab:** ```bash # Run every hour crontab -e # Add: 0 * * * * /root/stacks/scale-schedule.sh >> /var/log/maplefile-scaling.log 2>&1 ``` --- ## Troubleshooting ### Problem: Replica Won't Start **Symptom:** Service shows 2/3 replicas (one missing) **Diagnosis:** ```bash # Check service tasks docker service ps maplefile_backend --no-trunc # Look for ERROR or FAILED states # Common errors: # - "no suitable node" # - "resource constraints not met" # - "starting container failed" ``` **Solutions:** **If "no suitable node":** ```bash # Check node availability docker node ls # Check placement constraints docker service inspect maplefile_backend --format '{{.Spec.TaskTemplate.Placement}}' # Fix: Add more worker nodes or adjust constraints ``` **If "resource constraints":** ```bash # Check worker resources docker node inspect --format '{{.Description.Resources}}' # Fix: Add more memory/CPU or scale down other services ``` **If "container failed to start":** ```bash # Check logs docker service logs maplefile_backend --tail 100 # Fix: Resolve application error (database connection, etc.) ``` ### Problem: Uneven Load Distribution **Symptom:** One replica handling more traffic than others **Diagnosis:** ```bash # Check CPU/memory per replica docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile # Check request logs docker service logs maplefile_backend | grep "HTTP request" ``` **Causes:** - External load balancer pinning connections - Long-lived connections (WebSockets) - Some replicas slower (different hardware) **Solution:** ```bash # Ensure using Docker Swarm's built-in load balancer (ingress network) # Check service network mode docker service inspect maplefile_backend --format '{{.Spec.EndpointSpec.Mode}}' # Should be: vip (virtual IP for load balancing) # If not, update service docker service update --endpoint-mode vip maplefile_backend ``` ### Problem: Replica on Wrong Node **Symptom:** Replica running on node without required labels **Diagnosis:** ```bash # Check where replicas are running docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}" # Check node labels docker node inspect --format '{{.Spec.Labels}}' ``` **Solution:** ```bash # Add label to node docker node update --label-add maplefile-backend=true # Or force replica to move docker service update --force maplefile_backend ``` ### Problem: Can't Scale Down **Symptom:** `docker service scale` hangs or fails **Diagnosis:** ```bash # Check service update status docker service inspect maplefile_backend --format '{{.UpdateStatus.State}}' # Check for stuck tasks docker service ps maplefile_backend --no-trunc ``` **Solution:** ```bash # Cancel stuck update docker service update --rollback maplefile_backend # Force scale docker service update --replicas 1 --force maplefile_backend ``` ### Problem: Leader Election Issues (Multiple Leaders) **Symptom:** Scheduled tasks running multiple times **Diagnosis:** ```bash # Check logs for leader election messages docker service logs maplefile_backend | grep -i "leader" # Should see only one "Elected as leader" ``` **Cause:** Redis connection issues or split-brain **Solution:** ```bash # Restart all replicas to re-elect leader docker service update --force maplefile_backend # Verify single leader in logs docker service logs maplefile_backend --tail 50 | grep -i "leader" ``` --- ## Best Practices ### 1. Start Small, Scale Gradually ```bash # Don't go from 1 to 10 replicas immediately # Scale gradually: docker service scale maplefile_backend=2 # Test with 2 # Monitor for 30 minutes docker service scale maplefile_backend=3 # Increase to 3 # Monitor for 30 minutes docker service scale maplefile_backend=5 # Increase to 5 ``` ### 2. Always Scale Before Deploying ```bash # Scale up for safer deployments docker service scale maplefile_backend=3 docker service update --image ...new-image... maplefile_backend # Can scale back down after deployment succeeds ``` ### 3. Use Health Checks **Ensure stack file has health checks:** ```yaml services: backend: healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8000/health"] interval: 30s timeout: 5s retries: 3 start_period: 60s ``` ### 4. Monitor Resource Usage ```bash # Check BEFORE scaling docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" # If CPU < 50%, probably don't need to scale yet # If CPU > 70%, scale up # If CPU > 90%, scale urgently ``` ### 5. Document Scaling Decisions **Keep a scaling log:** ```markdown ## Scaling Log ### 2025-11-14 - Scaled to 3 Replicas - **Reason:** Marketing campaign expected to 3x traffic - **Duration:** 2025-11-14 to 2025-11-16 - **Command:** `docker service scale maplefile_backend=3` - **Result:** Successfully handled 3x traffic, CPU avg 45% - **Cost:** +$24/mo for 2 extra droplets ### 2025-11-16 - Scaled back to 1 Replica - **Reason:** Campaign ended, traffic back to normal - **Command:** `docker service scale maplefile_backend=1` - **Result:** Single replica handling load fine, CPU avg 35% ``` ### 6. Test Scaling in Non-Production First **If you have QA environment:** ```bash # Test scaling in QA ssh qa-manager docker service scale maplefile_backend_qa=3 # Verify works correctly # - Load balancing # - Leader election # - Database connections # - Performance # Then apply to production ssh dockeradmin@ docker service scale maplefile_backend=3 ``` ### 7. Plan for Database Connections **Each replica needs database connections:** ```bash # If you have 3 replicas with 2 connections each = 6 total connections # Ensure Cassandra can handle this # Check Cassandra connection limit (default: high) # Check Redis connection limit (default: 10000) # If scaling to 10+ replicas, verify database can handle connections ``` ### 8. Consider Cost vs Performance **Calculate costs:** ```bash # Current: 1 replica on worker-8 ($12/mo) # Total: $12/mo # Scaled: 3 replicas across 3 workers ($12/mo each) # Total: $36/mo (+$24/mo) # Is the performance gain worth $24/mo? # - If traffic justifies it: Yes # - If just for redundancy: Maybe use 2 replicas instead ``` ### 9. Use Placement Strategies **Spread across nodes for HA:** ```yaml deploy: placement: preferences: - spread: node.hostname # Spread across different nodes ``` **Or pack onto fewer nodes for cost:** ```yaml deploy: placement: preferences: - spread: node.id # Pack onto fewer nodes first ``` ### 10. Set Resource Limits **Prevent one replica from using all resources:** ```yaml services: backend: deploy: resources: limits: memory: 1G # Max 1GB per replica cpus: '0.5' # Max 50% of 1 CPU reservations: memory: 512M # Reserve 512MB cpus: '0.25' # Reserve 25% of 1 CPU ``` --- ## Quick Reference ### Essential Commands ```bash # Scale service docker service scale maplefile_backend=3 docker service update --replicas 3 maplefile_backend # Check replicas docker service ls | grep maplefile docker service ps maplefile_backend # Monitor resources docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" | grep maplefile # Check distribution docker service ps maplefile_backend --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}" # Scale down docker service scale maplefile_backend=1 # Force update (re-distribute replicas) docker service update --force maplefile_backend ``` ### Scaling Decision Matrix | CPU Usage | Memory Usage | Action | |-----------|--------------|--------| | < 30% | < 50% | **Scale down** or keep current | | 30-70% | 50-80% | **Keep current** (optimal) | | 70-85% | 80-90% | **Scale up** soon (planned) | | > 85% | > 90% | **Scale up now** (urgent) | ### Replica Count Guidelines | Traffic Level | Suggested Replicas | Cost | |---------------|-------------------|------| | Development | 1 | $12/mo | | Low (< 1000 req/day) | 1 | $12/mo | | Medium (1000-10000 req/day) | 2-3 | $24-36/mo | | High (10000-100000 req/day) | 5-10 | $60-120/mo | | Very High (> 100000 req/day) | 10+ | $120+/mo | --- ## Related Documentation - [Guide 12: Horizontal Scaling Setup](../setup/12_horizontal_scaling.md) - [Image Updates and Deployments](./IMAGE_UPDATES.md) - [Environment Variables Management](./ENVIRONMENT_VARIABLES.md) --- **Questions?** - Check service status: `docker service ls | grep maplefile` - Check replica distribution: `docker service ps maplefile_backend` - Monitor resources: `docker stats | grep maplefile` **Last Updated**: November 2025