A lightweight demo that simulates telecom incidents across U.S. cities and streams them into MongoDB. A React UI controls the simulator (EPS, spread, concurrency, seed) and shows live status; a Node/Express server generates events and writes them to MongoDB Atlas.
Simulation Controls (left panel)
- Incidents / sec: Target events per second (EPS) across all workers.
- Batch size: Insert batch size per tick; tune for throughput.
- Concurrency: Number of worker loops producing events in parallel.
- Spread (σ factor): Scales each city’s
sigmaKmto control geographic jitter (wider/narrower clouds). - Seed (optional): If set, makes runs deterministic (same cities, jitter, and serviceIssues each run with the same parameters).
Buttons & indicators
- Start Simulator / Stop: Begin/stop generation on the server.
- Refresh Status: Polls
/status(useful when the sim is running elsewhere). - IPS/Worker (chip): Approximate target load per worker = EPS / concurrency.
- Real IPS (MA) (green chip): Moving average of actual inserts/sec over a short window.
- Cities (blue chip): Size of the currently loaded city model.
Status panel
Shows the raw JSON from /status so you can verify the live configuration and throughput.
simulator/
server/
src/
config.js # env + sane defaults
db.js # Mongo client lifecycle + indexes
cityModel.js # loads cities with weight & sigmaKm
rng.js # deterministic RNG + gaussian jitter
serviceIssues.js # generates embedded telecom issues
simulator.js # the event generator engine
routes.js # /start /stop /status
server.js # express bootstrap + CORS + shutdown
package.json
.env.example
data/
us-cities.json # { name, lat, lng, weight, sigmaKm }[]
web/
(React UI app — controls & status)
- Node.js 18+ (works with 20/22/24)
- MongoDB Atlas cluster (or local MongoDB)
- npm (or pnpm/yarn)
- Install deps and make your env file:
cd simulator/server
npm i
cp .env.example .env- Edit
.env:
MONGODB_URI=mongodb+srv://<user>:<pass>@<cluster>/
DB_NAME=incidents
COLL_NAME=incident_events
PORT=5050
ALLOWED_ORIGIN=http://localhost:5173- Run:
npm run start
# or for auto-reload:
npm run devYou should see:
[server] listening on http://localhost:5050
-
GET /status→ current configuration and moving-average inserts/sec. -
POST /start(JSON body){ "eventsPerSec": 8000, "batchSize": 1000, "concurrency": 1, "spread": 2, "seed": 1234 } -
POST /stop→ stops all workers gracefully.
Each insert is a single incident event:
{
"type": "incident",
"ts": "2025-10-09T16:43:21.511Z",
"loc": { "type": "Point", "coordinates": [-77.4511, 40.9044] },
"city": "Aaronsburg",
"lat": 40.9044,
"lng": -77.4511,
"weight": 1,
"sigmaKm": 5,
"serviceIssue": {
"type": "broadband",
"accountId": "ATTB-102",
"issue": "slow-speeds",
"downstreamMbps": 5.4,
"expectedMbps": 100
}
}Notes
lat/lngare top-level for easy consumption by deck.gl.locenables geo queries (2dsphereindex created on startup).weightandsigmaKmare carried from the city model to drive map density/blur.serviceIssueis randomized per event (wireless, fiber, 5g, enterprise, etc.).
cd simulator/web
npm i
npm run devOpen the printed URL (typically http://localhost:5173).
The UI expects the server at http://localhost:5050 (CORS is pre-enabled via ALLOWED_ORIGIN).
-
City model:
server/data/us-cities.jsoncontains cities with{ name, lat, lng, weight, sigmaKm }.weightbiases selection frequency (bigger cities → more incidents).sigmaKmsets base spread; UI Spread multiplies this.
-
Sampling:
- A deterministic RNG (optional seed) picks cities weighted by
weight. - Coordinates are jittered around the city center using a Gaussian scaled by
sigmaKm * spread.
- A deterministic RNG (optional seed) picks cities weighted by
-
Issue enrichment:
- For each event,
serviceIssues.jscreates a telecom-flavored issue object. - Many types are modeled (broadband, wireless, fiber, 5g, VPN, backhaul, datacenter, etc.).
- Some IDs use a short code derived from the city name (first 3 uppercase chars).
- For each event,
-
Insertion:
- Workers insert batches each second to hit the target Incidents/sec.
/statusreports a moving average of actual inserts/sec.
Start a default 8k EPS simulation
# UI: set EPS=8000, Batch=1000, Concurrency=1, Spread=2.0, Seed empty
# Press “Start Simulator”Reproducible run
# Enter a number in Seed (e.g., 42) → same sequence every time with same params.Stress test
- Increase Concurrency (e.g., 4–8) and adjust Batch size (e.g., 2k–5k).
- Watch Real IPS (MA) to see actual sustained throughput.
Map visualizer (future)
- Feed
lat,lng, andweightdirectly into deck.gl layers (ScreenGridLayer,HexagonLayer, orScatterplotLayer). - Use
serviceIssue.typefor color/filters; optionally scale radius bysigmaKm.
-
Faker method not found: We avoid version-specific Faker APIs; if you still hit one, update
@faker-js/fakeror paste the providedserviceIssues.js(version-agnostic). -
CORS errors: Ensure
.envALLOWED_ORIGINmatches the UI URL. -
Throughput lower than target:
- Increase Batch size and/or Concurrency.
- Ensure your Atlas cluster tier can sustain the write rate (monitor metrics).
-
Non-deterministic runs with a seed:
- Confirm the seed field is a number.
- If using multiple workers and you want per-worker determinism, we can derive
seed + workerIndex.
What does “Seed” do? Makes the RNG deterministic. Same seed + same params + same city model ⇒ same event stream.
Why both lat/lng and loc?
lat/lng for visualization libraries; loc for Mongo geospatial queries and indexes.
Can I point to local MongoDB?
Yes—set MONGODB_URI=mongodb://localhost:27017 in .env.
How big is the city model?
Shown in the UI “Cities” badge (e.g., 20940). It’s loaded once at server start.
Server
cd simulator/server
npm run start # run
npm run dev # node --watchWeb
cd simulator/web
npm run dev- Add a “live map” tab in the UI using deck.gl, reading back the last N seconds.
- Toggle filters by
serviceIssue.typeand color by severity. - Per-worker derived seeds for deterministic parallelism.
- Optional Kafka or Atlas Stream Processing integration for downstream pipelines.