Skip to content

Stack Inventory

What is running, which version, why this choice, and what was rejected. Every entry links to the canonical source — usually package.json, docker-compose.yml, or an ADR.

This is a reference, not a tutorial. For a hands-on walk-through of the running stack, see ../onboarding/day-one.md. For trade-off discussions, follow the ADR pointers.


1. Languages

Language Where Version Notes
TypeScript All three repos 5.x Strict mode in ebit-api; FE repos inherit Next.js compiler defaults.
Node.js Runtime for all three 20 LTS Pinned in CI; Doppler-injected envs assume 20+.

Package managers (do not mix)

Per ../../CLAUDE.md — running the wrong tool corrupts the lockfile.

Repo Package manager Lockfile
ebit-api npm package-lock.json
ebit-fe pnpm (pnpm@9.11.0) pnpm-lock.yaml
ebit-admin-fe pnpm pnpm-lock.yaml
tests-e2e pnpm pnpm-lock.yaml

2. Backend stack — ebit-api

Component Version Why this Alternatives rejected ADR
NestJS 10.x Mature DI / module system; first-class OTel + Prisma + BullMQ ecosystem. Express bare, Fastify bare. NestJS gives us guards / interceptors / pipes that the auth + throttling layer leans on.
Prisma 6.x Type-safe Postgres client; multiSchema preview lets us split schema per app. TypeORM (heavy, mixed reputation), Drizzle (less mature for our scale). ADR-0006
Postgres 13 Default for local; matches ops target. Three logical schemas in one DB: public, blackjack, speed_roulette. One DB per app — rejected because cross-schema joins (e.g., UserBlackjackBet) need to stay cheap. ADR-0006
Redis (cache) 7.x BullMQ broker + sliding-window throttler + ONLINE_USERS zset + gateway pub/sub. Password cache, port 6379. Memcached (no pub/sub, no Lua).
Redis (bot) 7.x Isolation: bot fleet state lives on a separate instance (port 6380, password bot) so a runaway bot can't evict cache hot keys. Single Redis with separate DB index — rejected because BullMQ + bot writes share IO budget under load.
BullMQ latest via @nestjs/bullmq Production async work — auth session updates, bets, bots, challenges, leaderboard, promo, user-stats, skindeck deposits, both speed-roulette queues. RabbitMQ for app-level queues — rejected; only the stubbed Fast Track module talks to RabbitMQ. ADR-0003
RabbitMQ 3.x Wired into compose (vhost ft, port 5672 + UI 15672) but only to the stubbed Fast Track producer (apps/api/src/fast-track/rabbitmq/fast-track.rmq.module.ts:8 returns disabled = true). Receives zero traffic until the stub is removed. ADR-0003
socket.io 4.x via apps/rt/ Real-time event fan-out (/events namespace, websocket-only transport, polling disabled). Native ws (loses room semantics), SSE (one-way).

Five NestJS apps (one monorepo)

Declared in ebit-api/nest-cli.json; each has its own apps/<name>/, main.ts, and tsconfig.app.json. Shared logic lives under libs/ and is imported via TS path aliases.

App Port Role
api 4000 Public + admin REST, Swagger at /swagger
rt 4001 socket.io /events namespace, websocket-only
bj 4002 Blackjack server — architecturally orphaned (no in-repo FE calls it; dropbet hits api's house-game endpoints instead). See architecture.md §Known debt.
bo 4003 Backoffice; Swagger at /swagger
speed-roulette internal EOS-anchored speed roulette state machine

3. Frontend stack

ebit-fe (player-facing, branded dropbet)

Component Version Why this
Next.js 14 (App Router) SSR + RSC; matches @vercel/otel for trace propagation.
next-intl latest i18n with route tree under src/app/[locale]/; messages in messages/{en,de}.json.
Tailwind CSS 3.x Utility-first; pairs with shadcn primitives.
shadcn/ui latest Radix-based component library. Code is checked in, not vendored from npm.
@svgr/webpack *.svg → React component; *.svg?url → asset URL. Configured in next.config.js.
socket.io-client 4.x Connects to ebit-rt (websocket-only).
@vercel/otel pinned 1.x Browser + server OTel. Pinned because 2.x removed propagateContextUrls.

ebit-admin-fe (internal admin)

Component Version Why this
Vite 8.x Replaced Next.js — admin doesn't need SSR; SPA build is simpler and faster.
React 19.x Brought in with the Vite migration.
TanStack Router 1.x File-based routing under src/routes/ (replaces Next App Router groups).
Tailwind CSS 4.x Utility-first; via @tailwindcss/vite.
no i18n Single-language admin.

Admin-fe migrated from Next.js 14 → Vite + React 19. Known integration bugs around post-login auth and cross-service tracing still apply — see architecture.md §Known debt and the dedicated handover note. SSR-specific bugs no longer apply (no SSR in a Vite SPA).


4. Observability stack

Configs live under observability/ at the repo root.

Component Version / image Role
OpenTelemetry Collector otel/opentelemetry-collector-contrib:0.96.0 OTLP gRPC :4317 + HTTP :4318 ingress; spanmetrics connector; tail sampling; filelog/docker for EvoLogger records.
Jaeger v2.17 (jaegertracing/jaeger:2.17) + Badger backend Trace UI :16686. v1 was EOL'd 2025-12-31 and OOM'd at 19.2 GB on the dev VM.
Prometheus latest Metrics TSDB :9090.
Loki latest Log store :3100; receives pino records via OTLP and EvoLogger/winston records via filelog/docker.
Grafana latest UI :3003 (admin/grafana). Provisioned datasources + dashboards in observability/grafana/provisioning/.

Manual tracer.startActiveSpan wraps the critical paths (sign-in, bet-place); auto-instrumentation covers HTTP, Prisma, ioredis, BullMQ, pino, winston. See observability.md.


5. Auth + identity

Component Where Notes
JWT (access + refresh) apps/api/src/auth/ Cookie-based on the api side (access_token, refresh_token). admin-fe still has a legacy jwt_* cookie name path — see auth-bug note.
bcrypt apps/api/src/auth/auth.service.ts Password hashing.
2FA via JWT temp apps/api/src/auth/2fa/ JWT_MFA_TEMP_SECRET-signed temp token, exchanged for a real session on /auth/verify-2fa.
Sessions Redis cache TTL'd session keys; updates ride a BullMQ queue (session.queue-producer.ts).
Captcha reCAPTCHA + GeeTest Local-only bypass: x-captcha-token: pass works when NODE_ENV=local.

6. Infrastructure

Component Version Notes
AWS eu-north-1 Account 671543671262 for perf rig.
Terraform 1.9.x Modules under terraform/modules/; perf rig wiring under terraform/perf/.
Docker Compose 2.x Root docker-compose.yml glues the three repos + observability stack. Each repo also has its own Dockerfile.
ECR Image registry for staging/prod.
EBS gp3 Mounted volume for Jaeger Badger storage; sizing rationale in ../audits/jaeger-storage-research.md.

7. Dev tools

Tool Used by Where its config lives Daily command
Doppler All repos (secrets) ~/.config/doppler/token; service tokens at terraform/perf/secrets/ doppler secrets --project ebit-api --config dev_perf
Husky + lint-staged All repos .husky/, package.json auto-runs on commit
Sentry All apps sentry.*.config.ts; source maps via SENTRY_* build args DSN per app
Vitest ebit-api Matches *.test.ts and *.spec.ts npm test
Playwright tests-e2e/, tests-perf/playwright-canary/ playwright.config.ts pnpm playwright test
k6 tests-perf/k6/ per-scenario .js files k6 run scenarios/...
ESLint All repos .eslintrc.* npm run lint / pnpm lint (FE lint also runs tsc --noEmit)
Prettier All repos .prettierrc pnpm prettier-fix (ebit-fe)

8. Production-readiness notes

Stack-level gaps that block production, by component:

  • Trace propagation across @ExternalControllerClient (Redis pub/sub microservice transport) — three-hop speed-roulette flows surface as three uncorrelated traces in Jaeger. See ADR-0005 and ../audits/perf-trace-coverage-audit.md.
  • ebit-bj orphan — port 4002 is exposed by compose but no in-repo client reaches it; dropbet's blackjack uses apps/api/src/casino/house/blackjack/. Disposition (delete vs proxy) is open.
  • RabbitMQ stub — Fast Track module returns disabled = true; broker receives zero traffic. See ADR-0003.
  • EvoLogger / winston records reach Loki only via the filelog scrape, not OTLP — distinguished by source=docker_filelog. Trace-correlation fields are present but service.name resource attribute is missing on this path. See ADR-0007.
  • ebit-admin-fe cross-service tracing is broken — three stacked bugs (cookie name mismatch, silent middleware fall-through, missing @vercel/otel) prevent successful post-login SSR. See architecture.md §Known debt.

For perf-test-readiness specifics see performance.md and ../perf-run-checklist.md.