Skip to content

About

Microservice ingesting real-time price ticks from multiple upstream providers (exchanges/vendors), aggregates them into a single authoritative price per symbol, and serves that price via REST (pull) and WebSocket (push) to downstream consumers

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

JVM Stock Pricer — Java vs Kotlin

Side-by-side stock price aggregators for comparing Java 21 virtual threads + Spring Boot vs Kotlin coroutines + Ktor on the same live-data workload.

Both services pull prices from Yahoo Finance and Stooq, apply per-provider:symbol retry + circuit breaker, keep an in-memory history ring buffer, and expose identical REST + WebSocket APIs plus a Chart.js dashboard.

Module Stack Default port
kotlin-aggregator/ Ktor + coroutines + kotlinx.serialization 8080
java-aggregator/ Spring Boot 3.4 + virtual threads + Jackson 8081

Design background: stock-aggregator-java-vs-kotlin.md.

Docs: index · dual-run runbook · Kotlin runbook · Java runbook · simultaneous analysis guide

Requirements

  • JDK 21+
  • Outbound HTTPS to query1.finance.yahoo.com and stooq.com

Run both (for comparison)

# Terminal 1 — Kotlin
./gradlew :kotlin-aggregator:run

# Terminal 2 — Java
./gradlew :java-aggregator:bootRun

Then open:

curl http://localhost:8080/prices
curl http://localhost:8081/prices

Full dual-run steps (identical env, warm-up, clean stop): docs/runbooks/dual-run.md.
How to benchmark both at once: docs/ANALYSIS.md.

Shared API contract

Endpoint Purpose
GET / Chart.js dashboard
GET /symbols Configured tickers
GET /prices All latest aggregated prices
GET /prices/{symbol} One symbol (404 if none yet)
GET /prices/{symbol}/history In-memory history ring buffer
WS /ws/prices Push every update as JSON (seeds cache on connect)

Shared configuration (environment variables)

Variable Default Meaning
SYMBOLS AAPL,MSFT,GOOG Comma-separated tickers
POLL_INTERVAL_MS 5000 Per-symbol poll interval
PROVIDER_TIMEOUT_MS 3000 Per-attempt provider timeout
MAX_RETRIES 2 Extra attempts with exponential backoff
RETRY_BASE_DELAY_MS 200 Backoff base (200, 400, 800, ...)
HISTORY_SIZE 200 Max history points per symbol
CB_FAILURE_THRESHOLD 3 Failures before circuit opens
CB_RESET_TIMEOUT_MS 30000 Open-circuit cool-down
PORT 8080 (Kotlin) / 8081 (Java) HTTP/WebSocket port

Example:

SYMBOLS=AAPL,TSLA,NVDA POLL_INTERVAL_MS=10000 ./gradlew :kotlin-aggregator:run
PORT=8081 SYMBOLS=AAPL,TSLA,NVDA POLL_INTERVAL_MS=10000 ./gradlew :java-aggregator:bootRun

What differs (the point of the comparison)

Concern Kotlin Java
Concurrency supervisorScope + coroutines + withTimeoutOrNull Virtual-thread executor + blocking HTTP + futures/timeouts
HTTP server Ktor Netty Spring MVC (+ VT-enabled request threads)
Serialization kotlinx.serialization Jackson
Fan-out SharedFlow → WebSocket Listener/ConcurrentHashMap of sessions → WebSocket

Build / test

./gradlew :kotlin-aggregator:test :java-aggregator:test
./gradlew build

Tracking

Progress is tracked with beads (bd). Epic: Java vs Kotlin stock price aggregators.

About

Microservice ingesting real-time price ticks from multiple upstream providers (exchanges/vendors), aggregates them into a single authoritative price per symbol, and serves that price via REST (pull) and WebSocket (push) to downstream consumers

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages