/api/simulationsStart by creating a simulation with a few cloud resources. Here we build a minimal AWS web-app: a load balancer, an auto-scaling compute tier, and a database. The response contains the simulation ID — copy it, you will use it in every subsequent step.
curl -X POST https://www.cloudworldmodel.ai/api/simulations \-H "Authorization: Bearer cwm_live_YOUR_KEY" \-H "Content-Type: application/json" \-d '{"name": "My First Simulation","traffic": 5000,"resources": [{"id": "r1","name": "ALB","type": "network","provider": "aws","serviceFamily": "elb","region": "us-east-1","config": { "tier": "standard", "targetCapacity": 10000 }},{"id": "r2","name": "App Server","type": "compute","provider": "aws","serviceFamily": "ec2","region": "us-east-1","config": {"instanceType": "t3.large","instances": 4,"autoScaling": true,"minInstances": 2,"maxInstances": 12}},{"id": "r3","name": "Primary DB","type": "database","provider": "aws","serviceFamily": "rds","region": "us-east-1","config": { "instanceType": "db.r5.large", "multiAZ": true }}]}'
{"id": "sim-abc123","name": "My First Simulation","status": "running","provider": "aws","region": "us-east-1","traffic": 5000,"resources": [{ "id": "r1", "name": "ALB", "type": "network", "status": "healthy" },{ "id": "r2", "name": "App Server", "type": "compute", "status": "healthy" },{ "id": "r3", "name": "Primary DB", "type": "database", "status": "healthy" }],"createdAt": "2024-01-15T10:00:00Z"}
What to copy: Copy the id field (sim-abc123). Every request below uses it as {simulationId} in the path.
/api/simulations/{simulationId}/stepA step runs the capacity model: it applies active traffic patterns, calculates CPU usage, latency, and error rate for each resource, fires autoscaling logic, and records events. Call this endpoint repeatedly to move the clock forward. The response includes a metrics snapshot for this instant.
curl -X POST https://www.cloudworldmodel.ai/api/simulations/sim-abc123/step \-H "Authorization: Bearer cwm_live_YOUR_KEY"
{"simulation": {"id": "sim-abc123","status": "running","traffic": 5000,"stepCount": 1},"metrics": {"simulationId": "sim-abc123","cpuUsage": 72.4,"latencyP50": 45,"latencyP95": 120,"errorRate": 0.3,"throughput": 4850,"costPerHour": 2.40,"timestamp": "2024-01-15T10:01:00Z"},"events": [{"id": "evt-001","severity": "info","message": "Step 1 complete — 4 app-server instances healthy"}]}
What to copy: Note the metrics values (cpuUsage, latencyP95, costPerHour). After several steps these feed the right-sizing analysis in Step 6.
/api/simulations/{simulationId}/patternsA traffic pattern modifies traffic load on every subsequent step. Patterns can be sine waves (daily cycles), ramps (gradual load builds), step functions (sudden jumps), or spikes. Multiple patterns can coexist — their effects are composed. Once registered, a pattern is automatically applied on every future step. Step 4 shows the one-shot spike alternative — set up the sustained pattern here first so your autoscaler has a realistic baseline before the spike hits.
curl -X POST https://www.cloudworldmodel.ai/api/simulations/sim-abc123/patterns \-H "Authorization: Bearer cwm_live_YOUR_KEY" \-H "Content-Type: application/json" \-d '{"type": "sine","amplitude": 0.3,"period": 24}'
{"id": "pat-xyz789","simulationId": "sim-abc123","type": "sine","amplitude": 0.3,"period": 24,"isActive": true}
What to copy: The sine pattern is now active. Every step call will apply ±30% traffic oscillation with a 24-step period, simulating a daily load cycle.
/api/simulations/{simulationId}/inject-trafficFor a more immediate stress test — without configuring a full pattern — hit the inject-traffic endpoint. It multiplies the current traffic by a random 2×–5× factor and records a warning event. Run a few more step calls afterwards to see how the autoscaler responds to the surge.
curl -X POST https://www.cloudworldmodel.ai/api/simulations/sim-abc123/inject-traffic \-H "Authorization: Bearer cwm_live_YOUR_KEY"
{"simulation": {"id": "sim-abc123","traffic": 18500,"status": "running"},"event": {"id": "evt-spike-001","simulationId": "sim-abc123","severity": "warning","message": "Traffic spike injected: 5000 → 18500 RPS"}}
What to copy: Traffic jumped from 5 000 to 18 500 RPS. Call POST /step two or three more times to watch autoscaling add instances and latency stabilise.
/api/simulations/{simulationId}/metricsRead back the full time-series of every metrics snapshot recorded so far. Each entry corresponds to one step call and includes CPU, latency percentiles, error rate, throughput, and cost. Use this to chart how your architecture behaved across the entire scenario.
curl https://www.cloudworldmodel.ai/api/simulations/sim-abc123/metrics \-H "Authorization: Bearer cwm_live_YOUR_KEY"
[{"simulationId": "sim-abc123","cpuUsage": 72.4,"latencyP50": 45,"latencyP95": 120,"latencyP99": 198,"errorRate": 0.3,"throughput": 4850,"costPerHour": 2.38,"timestamp": "2024-01-15T10:01:00Z"},{"simulationId": "sim-abc123","cpuUsage": 88.1,"latencyP50": 72,"latencyP95": 210,"latencyP99": 380,"errorRate": 2.1,"throughput": 6200,"costPerHour": 2.85,"timestamp": "2024-01-15T10:02:00Z"},{"simulationId": "sim-abc123","cpuUsage": 41.3,"latencyP50": 31,"latencyP95": 88,"latencyP99": 142,"errorRate": 0.1,"throughput": 5100,"costPerHour": 2.85,"timestamp": "2024-01-15T10:03:00Z"}]
What to copy: Three steps recorded. The middle entry (cpuUsage 88.1%) shows peak stress during the spike. After autoscaling added instances, utilisation fell back to 41.3% — possibly over-provisioned. Step 6 will check.
/api/simulations/{simulationId}/right-sizing-hintThe right-sizing endpoint analyses the most recent metrics and resource configuration to detect over-provisioning. When it finds under-utilised resources it returns a recommended smaller size slug, the estimated hourly rate, the potential savings percentage, and a trade-off note so you can make an informed decision before resizing.
curl https://www.cloudworldmodel.ai/api/simulations/sim-abc123/right-sizing-hint \-H "Authorization: Bearer cwm_live_YOUR_KEY"
{"hasHint": true,"hints": [{"resourceType": "compute","reason": "low_cpu","affectedResourceId": "r2","affectedResourceName": "App Server","recommendedSlug": "t3.medium","hourlyRate": 0.052,"estimatedSavingsPct": 35,"tradeOffNote": "t3.medium has half the vCPU of t3.large — monitor p95 latency closely after resize","currentUtilization": 22.4}]}
What to copy: App Server is running at 22.4% CPU — well below the efficient range. Downsizing to t3.medium would save ~35% on compute costs. The tradeOffNote flags the reduced headroom so you can decide whether the savings are worth it.
Aurora Serverless v2 (aurora-serverless) scales ACUs continuously between minCapacity and maxCapacity, so cost tracks actual load rather than peak provisioned size. The simulation engine models a 2–4 step ACU ramp delay after add_resource — during those steps cpu_util reads 0 and cost_usd_hr reflects only the minCapacity floor (~$0.06/hr at 0.5 ACUs). Once the workload is routed to the resource, cost_usd_hr climbs incrementally over 3–6 steps to the steady-state ACU-proportional rate. The snippet below handles both phases so your reward function avoids false latency penalties during ramp-up.
import requestsBASE = "https://www.cloudworldmodel.ai/api"HEADERS = {"Authorization": "Bearer <your-api-key>", "Content-Type": "application/json"}# 1. Create an RL environment linked to an existing simulation that already contains# at least one AWS database resource (the engine clones it for the new step).env = requests.post(f"{BASE}/rl/environments",json={"simulationId": "<sim-id>","episodeConfig": {"maxSteps": 40, "tick_seconds": 60}},headers=HEADERS).json()env_id = env["environment"]["id"]# 2. add_resource action — adds an AWS database resource to the running simulation.# The engine models a 2-4 step ACU scale-out delay for aurora-serverless targets.# Step request shape: {"action": {"type": "...", "parameters": {...}}, "tick_seconds": N}step1 = requests.post(f"{BASE}/rl/environments/{env_id}/step", headers=HEADERS, json={"action": {"type": "add_resource","parameters": {"resourceType": "database", "provider": "aws"}},"tick_seconds": 60}).json()# Step response keys: t, obs, metrics, reward, reward_components, donet = step1["t"] # step index (1 after first action)obs = step1["obs"] # {cpu_util, rps, instances, traffic, currentTime}metrics = step1["metrics"] # {cost_usd_hr, latency_p95, error_rate, uptime, sla_violations}# 3. Ramp window (t = 1-4): obs.cpu_util == 0, metrics.cost_usd_hr at minCapacity floor (~$0.06/hr).# Use a neutral adjust_threshold action to advance the clock without changing autoscaling config.# Only count cost + stability reward components -- skip performance and sla during ACU ramp-up.RAMP_STEPS = 4result = step1for _ in range(RAMP_STEPS):result = requests.post(f"{BASE}/rl/environments/{env_id}/step", headers=HEADERS, json={"action": {"type": "adjust_threshold", "parameters": {"cpuThreshold": 70}},"tick_seconds": 60}).json()t = result["t"]obs = result["obs"]metrics = result["metrics"]rc = result["reward_components"]# Exclude performance and sla components during ACU ramp to avoid false latency penaltiesadjusted_reward = rc["cost"] + rc["stability"]print(f"Ramp t={t:2d} cpu_util={obs['cpu_util']:.3f} "f"cost_usd_hr={metrics['cost_usd_hr']:.4f} adj_reward={adjusted_reward:.3f}")# 4. Steady-state training (t >= 5): all reward components are now meaningful. With a database# resource present this is five components — performance, cost, stability, sla, and the# connection_pressure DB-pool penalty (see the worked connection-pool example below).# metrics.cost_usd_hr climbs over 3-6 steps toward the ACU-proportional steady-state rate.done = result["done"]while not done:result = requests.post(f"{BASE}/rl/environments/{env_id}/step", headers=HEADERS, json={"action": {"type": "adjust_threshold", "parameters": {"cpuThreshold": 70}},"tick_seconds": 60}).json()t = result["t"]obs = result["obs"]metrics = result["metrics"]reward = result["reward"]done = result["done"]print(f"Train t={t:2d} cpu_util={obs['cpu_util']:.3f} "f"latency_p95={metrics['latency_p95']:.0f}ms "f"cost_usd_hr={metrics['cost_usd_hr']:.4f} reward={reward:.3f}")# 5. Reset for the next episoderequests.post(f"{BASE}/rl/environments/{env_id}/reset", headers=HEADERS)
Key behaviors to expect
cpu_util is 0 and cost_usd_hr ≈ $0.06/hr. Only count cost + stability reward components — skip performance and sla to avoid false penalties.performance, cost, stability, sla. cpu_util stabilises at 20–70% for OLTP workloads. cost_usd_hr ramps over 3–6 more steps to the ACU-proportional rate (up to ≈ $1.92/hr at 16 ACUs).connection_pressure (and a matching metrics.connection_pressure ratio). It is 0 while the pool is under capacity and turns negative once active connections exceed maxConnections — scale the database (not just compute) when it approaches 1.0.minCapacity breakeven, cost_usd_hr reverts to the floor within 1–2 steps.cpu_util == 0 and floor-cost_usd_hr signals above are visible at the top level only in this single-serverless-DB quickstart. When the simulation also runs a busy compute tier or other databases, the sim-wide cpu_util, cost_usd_hr, and connection_pressure are aggregates that mask one DB's warming window, ACU floor, and pool saturation. Read metrics.serverless[i] — one entry per Aurora Serverless v2 DB, each exposing its own cpu_util, acu, warming, cost_usd_hr, and connection_pressure.Chaos engineering
Register failure scenarios (database crash, zone outage, network partition) and measure your architecture's resilience score.
Hybrid prediction engine
Step via the hybrid endpoint to blend rule-based simulation with ML-based prediction and compare the two paths side by side.