I built ElasticMind, a Python machine-learning-driven cloud resource manager described as a repository on my GitHub. It forecasts workload and allocates capacity with a predictive controller and reactive fallback, evaluating accuracy, utilization, latency, cost, and energy. The project started in 2026-10 and was last updated in 2026-10.
I use LightGBM for multi-horizon forecasts at 5, 15, and 30 minutes, with P50/P90 quantile outputs; Holt-Winters and persistence are comparison baselines. Predictive desired capacity is computed from P90, capacity per instance, and target utilization, with headroom, minimum and maximum capacity, fast scale-up, slow scale-down, cooldowns, and hysteresis. The latency safety net requires a windowed p95 breach for three consecutive ticks and utilization >= 0.30, or a non-zero error rate.
loadgen → gateway → replica pool → gateway metrics → backend → predictor → autoscaler → capacity actuator → gateway replica pool
React dashboard ← backend JSON API
desired = ceil(P90 / (capacity_per_instance × target_util))
I run a fully local, reproducible lab that replays a one-minute trace with provisioning delay and reports utilization, SLA violations, M/M/c-style latency, cost, and energy. All local-lab numeric results are simulated; the simulator, power model, and cost figures are labelled [simulated] in code and in the dashboard. The README points to docs/ASSUMPTIONS.md for the assumptions behind these figures. The captured project description does not include measured benchmark results.
I include a reactive safety net, rolling-MAPE drift alarm, confidence-aware headroom, and automatic fallback to reactive operation on drift. My React, Vite, TypeScript, Tailwind, and Recharts dashboard replaces Grafana and polls the backend every 5 seconds.
- ml/: data, features, models, training, and evaluation.
I intend to deploy the same controller to AWS ECS Fargate using Terraform; ECS Fargate, ALB, S3, and CloudWatch are identified as Phase 2. The captured description does not specify actual forecast accuracy, utilization, latency, SLA violations, cost or energy results, detailed simulation assumptions, controller tuning values, or the status and details of the AWS deployment.
- backend/: FastAPI, autoscaler, simulator, robustness, and SQLite.
- frontend/: React dashboard.
- loadgen/: asynchronous Python traffic generator.
- gateway/: FastAPI round-robin gateway and CPU-burn replica pool.
- target_app/: standalone target service for local experiments.
- infra/: Docker Compose, Dockerfiles, and Terraform.
- experiments/: scripted runs and results.
- docs/: architecture, assumptions, report, and demo script.
I use the shared Settings model in the backend and experiment scripts; the load generator reads ELASTICMIND_TIME_SCALE directly and spaces HTTP requests according to the profile at that speed-up factor. At ELASTICMIND_TIME_SCALE=10, each simulated minute takes six wall-clock seconds. The settings cover the profile, control interval, forecast horizon, target utilization, replica capacity and bounds, startup and drain delays, latency SLA, price and power assumptions, cooldowns, and safety utilization threshold. Scale-up and scale-down cooldowns default to 30 and 120 simulated seconds, which become 30/TIME_SCALE and 120/TIME_SCALE wall-clock seconds. Latency safety also uses SAFETY_MIN_UTILIZATION (0.30), SAFETY_LATENCY_BREACH_TICKS (3), and SAFETY_LATENCY_WINDOW_SIZE (5).
python -m venv .venv && source .venv/Scripts/activate # Windows
pip install -e ./ml -e ./backend -e ./loadgen -e ./gateway -e ./target_app
pip install pytest ruff black
python -m ml.data.generate --profile diurnal --days 14 --out ml/data/generated/diurnal.parquet
python -m ml.train --data ml/data/generated/diurnal.parquet --stride 30 --max-points 25
# -> experiments/results/model_comparison.csv + ml/models/artifacts/*.joblib
python -m experiments.run_eval --trace ml/data/generated/diurnal.parquet
python -m experiments.run_misprediction
# -> experiments/results/{policy_comparison,misprediction_scenarios}.csv (+ PNGs)
I generate 14 days of diurnal data, train with --stride 30 --max-points 25, then run evaluation against the generated trace and the misprediction experiment. Training writes experiments/results/model_comparison.csv and model artifacts under ml/models/artifacts/*.joblib; experiments write experiments/results/{policy_comparison,misprediction_scenarios}.csv and PNGs.
make up # backend + gateway + frontend
make demo # train if needed, start stack, loadgen, misprediction scenario
make down
./scripts/demo.ps1
./scripts/smoke_test.ps1
make test # pytest across ml/ backend/ loadgen/ target_app/
make lint # ruff + black --check + tsc
I use the PowerShell demo and smoke-test scripts instead of make on Windows. The dashboard is at http://localhost:5173, API documentation at http://localhost:8000/docs, gateway health at http://localhost:8001/health, and the gateway replica pool at http://localhost:8001/replicas. The gateway accepts GET /work, records request ID, status, replica ID, and latency at GET /requests, and publishes interval metrics to the backend.
I can scale the local replica pool with PUT /replicas and JSON {"desired": 4}. Worker service time and saturation are configured with GATEWAY_CPU_BURN_MS, GATEWAY_CONCURRENCY_PER_REPLICA, and GATEWAY_QUEUE_LIMIT.
I treat AWS as Phase 2: from infra/terraform, I initialize Terraform, plan and apply, record the demo, and then run terraform destroy to keep costs low. The quickstart points to the Terraform README for deployment details. For the assignment, I use the stages Problem → Identify → Choose → Design → Evaluate → Discuss and the docs/REPORT_TEMPLATE.md template.
I still need to replace the Dashboard and Compare experiments screenshot placeholders with my own captures. The quickstart lists the shared settings fields but does not give actual values for the other settings; it links to, rather than reproduces, the Terraform README and report template.