Skip to content

Tooling — Daily Drivers

Per-tool reference: what it is, where its config lives, daily commands. Targeted at developers who need to know the right invocation, not first-time users (for that read ../onboarding/day-one.md).

The list below is in roughly the order you encounter them on a typical workday.


Doppler — secrets management

What: Cloud-hosted secrets manager. Replaces .env files in staging / prod / perf. Local dev still uses .env for speed.

Workspace: ebit-devops (slug 4d59619bf8c6f858715b). Three projects: ebit-api, ebit-fe, ebit-admin-fe. See env.md §Doppler.

Config / state: - Personal admin token: ~/.config/doppler/token (chmod 600), loaded by ~/.bashrc. - Service tokens (container runtime): terraform/perf/secrets/doppler-token-* (gitignored). - run_local.sh in each repo expects DOPPLER_TOKEN exported.

Daily commands:

doppler secrets --project ebit-api --config dev_perf
doppler secrets set KEY="value" --project ebit-api --config dev_perf
doppler run --token <service-token> -- node main.js     # container-style

More: reference_doppler_workspace memory; ../audits/doppler-perf-audit.md.


Terraform — infra-as-code

What: Provisions AWS infra for the perf rig (eu-north-1). Modules at terraform/modules/ (monitoring + app); rig-level wiring at terraform/perf/.

Config / state: - terraform/perf/main.tf, variables.tf, outputs.tf, versions.tf, providers.tf. - terraform/perf/terraform.tfvars — populate from .tfvars.example before apply. - State stored locally at terraform/perf/terraform.tfstate (note: not S3-backed today; a single-engineer setup). - terraform/perf/loadgen-user-data.sh — cloud-init for the loadgen VM.

Daily commands:

cd terraform/perf
terraform init
terraform plan        # expect ~58 adds before first apply
terraform apply -auto-approve
terraform output -json > /tmp/perf-outputs.json   # save URLs / IPs
terraform destroy     # after the perf retention window


Docker Compose — local stack

What: Glues the three repos + observability stack for local dev. Single root docker-compose.yml.

Config / state: - /home/ubuntu/ebit/docker-compose.yml — services, ports, env, volumes. - Per-repo Dockerfiles inside ebit-api/, ebit-fe/, ebit-admin-fe/. - ebit-api/docker-compose.local.yml — backend-only infra (Postgres + 2 Redis + RabbitMQ). Used when you only need the data tier locally and run NestJS apps on the host.

Daily commands:

docker compose up -d                          # full stack from /home/ubuntu/ebit/
docker compose logs -f ebit-api               # tail one service
cd ebit-api && npm run dockers:infra          # backend infra only (Postgres / Redis / RMQ)

Ports: see stack.md §"Five NestJS apps" + architecture.md.


Prisma — DB schema + migrations

What: Type-safe Postgres client. Schema is split across three files (api.prisma, blackjack.prisma, speed_roulette.prisma) — see data-model.md.

Config / state: - ebit-api/libs/_prisma/src/schema/*.prisma — schemas. - ebit-api/package.json "prisma.schema" field — points at the schema folder. - ebit-api/libs/_prisma/src/seed/index.ts — seed entrypoint.

Daily commands (from ebit-api/):

npm run db:migrate:dev       # generate + apply migration vs .env DB
npm run db:seed              # run seed/index.ts
npm run db:reset             # drop, re-migrate, re-seed
npm run prisma:test:reset    # same vs .env.test DB

Always use the npm scripts — they wrap prisma with env-cmd -f .env. Calling npx prisma directly skips the env file.


k6 — load generation

What: Synthetic HTTP + WS load. Native Prometheus remote-write integration.

Config / state: - tests-perf/k6/scenarios/*.js — per-scenario scripts. - tests-perf/k6/lib/*.js — shared helpers. - tests-perf/k6/smoke.js — 50-VU pre-flight. - tests-perf/profiles/ — ramp profile definitions.

Daily commands (from tests-perf/):

k6 run k6/smoke.js                                # 50 VU pre-flight
k6 run -e BASE_URL=http://sut:4000 k6/scenarios/signin-storm.js
k6 run --out experimental-prometheus-rw=... k6/scenarios/bet-place-storm.js

More: performance.md, ../performance-testing.md, ../../tests-perf/README.md.


Playwright — E2E + canary

What: Browser-driven E2E (tests-e2e/) and real-browser canary during perf runs (tests-perf/playwright-canary/).

Config / state: - tests-e2e/playwright.config.ts, tests-perf/playwright-canary/playwright.config.ts. - Per-spec *.spec.ts files. Auth helpers + Jaeger trace assertions live in shared utils.

Daily commands:

cd tests-e2e && pnpm playwright test                                          # full E2E suite
cd tests-e2e && pnpm playwright test tests/dropbet-signin.spec.ts             # one test
cd tests-perf/playwright-canary && pnpm exec playwright install chromium      # first-time
cd tests-perf/playwright-canary && DURATION=600 LOAD_STAGE=ramp10k pnpm canary


Vitest — unit + integration tests (ebit-api)

What: Test runner for ebit-api. Matches *.test.ts and *.spec.ts.

Config / state: - ebit-api/vitest.config.ts (or per-app override). - Test DB env in ebit-api/.env.test; npm run prisma:test:reset seeds it.

Daily commands (from ebit-api/):

npm test                                           # all
npm test -- path/to/file.test.ts                   # single file
npm test -- -t "pattern"                           # single test by name


ESLint + Prettier

What: Linting + formatting. All three repos use Husky + lint-staged so commits auto-run.

Daily commands:

# ebit-api
cd ebit-api && npm run lint         # eslint --fix on {src,apps,libs,test}/**/*.ts

# ebit-fe / ebit-admin-fe
cd ebit-fe && pnpm lint             # next lint --max-warnings=0 + tsc --noEmit (both must pass)
cd ebit-fe && pnpm tsc              # type-check only
cd ebit-fe && pnpm prettier-fix     # ebit-fe only

pnpm lint exits non-zero on any warning — treat warnings as build breakers.


Sentry — error monitoring

What: Production error aggregation for all three apps + browser-side ebit-fe.

Config / state: - sentry.*.config.ts in each repo (server, client, edge configs for Next.js). - @sentry/nestjs in ebit-api; @sentry/nextjs in the FEs. - DSN per app: SENTRY_DSN_* env vars (5 in ebit-api). - Source maps uploaded at build time via SENTRY_AUTH_TOKEN + SENTRY_ORG + SENTRY_PROJECT_*.

Daily commands: errors land in the Sentry dashboard; nothing to run. To verify locally, NODE_ENV=production is required (Sentry is disabled in local).


Grafana — observability UI

What: Unified UI for traces (Jaeger datasource), metrics (Prometheus), logs (Loki).

Access: http://localhost:3003 (admin / grafana).

Config / state: - Datasources: observability/grafana/provisioning/datasources/datasources.yml. - Dashboards: observability/grafana/provisioning/dashboards/*.json (9 dashboards, see observability.md).

Daily use: Explore tab for ad-hoc queries; dashboards for routine reads. Trace pivot from a Loki log line via provisioned derivedFields.

Recipe: ../recipes/add-grafana-dashboard.md.


Jaeger UI — trace viewer

What: Trace search + waterfall view. Authoritative for every flow-doc trace ID.

Access: http://localhost:16686.

Daily use: - Search by service + operation: pick ebit-apiPOST /casino/games/house/dice/bet → click a trace. - Search by trace ID: paste from a log line or browser devtools. - Compare traces side-by-side from the search results page.

Storage: Jaeger v2 + Badger on local EBS (50 GB gp3, ttl.spans: 72h). See ../audits/jaeger-storage-research.md.


Loki — log queries

What: LogQL log store. Two ingestion paths (OTLP-bridged pino, filelog/docker for EvoLogger).

Access: http://localhost:3100 (HTTP API); usually queried through Grafana.

Daily use:

# trace-correlated logs across all services
{service_name="ebit-api"} |= "<trace_id>"

# EvoLogger / winston records (filelog path)
{source="docker_filelog"} |= "EvoLogger"

# error-level only
{service_name="ebit-api"} | json | level="error"


Prometheus — metric queries

What: Metrics TSDB. Includes spanmetrics-derived RED metrics from the OTel Collector.

Access: http://localhost:9090.

Daily PromQL:

# Span-derived rate
rate(traces_spanmetrics_calls_total{span_name=~"prisma:.*"}[5m])

# Span-derived p95
histogram_quantile(0.95,
  sum by (le, span_name) (rate(traces_spanmetrics_duration_milliseconds_bucket{span_name=~"prisma:.*"}[5m])))

# k6 load
rate(k6_http_reqs_total{scenario=~"$scenario"}[1m])
k6_vus{scenario=~"$scenario"}

# BullMQ queue depth
bullmq_queue_jobs{state="wait"}


Husky + lint-staged

What: Pre-commit hook runner. Auto-runs ESLint + Prettier on staged files.

Config / state: .husky/ in each repo; lint-staged config in each package.json.

Daily use: invisible. Commits auto-format and lint; failing commits surface a non-zero exit.


See also

  • stack.md — versions and rationale for each of these tools.
  • env.md — Doppler / env-var details.
  • observability.md — Grafana / Jaeger / Loki / Prometheus deep dive.
  • performance.md — k6 / Playwright daily commands within the perf workflow.
  • ../recipes/ — copy-paste recipes for adding endpoints, models, queues, spans, dashboards, tests.