Operations
1. Deployment
| Property | Value |
|---|---|
| Image | registry/pricing:<tag> |
| Container Port | 3000 (external 31070) |
| Probes | GET /healthz (live), GET /readyz (ready) |
| Snowflake ID | 7 (APP_ENV_NODE_ID) |
| Run modes | api (REST + CDC consumer at boot) · migrate (run-once seed) |
| Dependencies at boot | PostgreSQL (pricing schema), Redis (auth cache), Kafka (binding throws if APP_ENV_KAFKA_BROKERS empty) |
Kafka is a hard boot dependency:
ApplicationKafkaComponent.binding()throwsInternalServerErrorif brokers are unset, even though pricing only consumes (does not produce). A pod with no reachable broker will not start.
Traefik labels
yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.pricing.rule=PathPrefix(`/v1/api/pricing`)"
- "traefik.http.services.pricing.loadbalancer.server.port=3000"2. Observability
| Signal | Source | Where to look |
|---|---|---|
| Logs | stdout (IGNIS structured key-value) | kubectl logs <pod> / Loki |
| Health | GET /healthz, GET /readyz | Gateway portal |
| OpenAPI | GET /doc (Scalar), /doc/openapi.json | Live API explorer |
Key log markers
| Marker | Source | Meaning |
|---|---|---|
SKIP — FareSet already exists | PricingWorkerService | CDC idempotency hit (expected on RETRIEVE replays) |
DONE FareSet + SALE Fare seeded via CDC | PricingWorkerService | New variant priced |
DONE FBT override seeded | PricingWorkerService | FBT override child fare created |
Received message | Topic: %s | ApplicationKafkaComponent | CDC message ingested |
Unknown topic — subscribed but no handler | ApplicationKafkaComponent | Misconfigured subscription |
3. Security
| Concern | Mitigation |
|---|---|
| AuthN | JWT (ES256, JWKS from identity); BASIC for service-to-service (sale → pricing) |
| AuthZ | Casbin via PolicyDefinition; resource-based per controller; cached in Redis |
| Secrets | K8s Secret mounted as env (DB URL, Kafka SASL, basic-auth) |
| TLS | Terminated at gateway; Kafka SASL optional |
| Network policy | Cilium — allow gateway + sale + Kafka + Postgres + Redis only |
| Soft-delete | deletedAt — no hard-delete by default |
4. Runbook
4.1 Alert classes
| Alert | Trigger | Check | Fix | Escalate |
|---|---|---|---|---|
pricingHighErrorRate | 5xx >5% over 5m | logs level=error | inspect calculator errors / DB reachability | on-call backend |
pricingCheckoutRejects | spike in 4xx on /simulation* | logs for "no active fare set" | confirm CDC worker is seeding FareSets | on-call backend |
pricingCdcStalled | CDC offset not advancing | broker reachability + consumer group lag | restart pod / check Debezium | on-call SRE |
pricingBootCrashLoop | pod restarts | logs Cannot start Kafka — env ... empty | set APP_ENV_KAFKA_BROKERS | on-call SRE |
4.2 Common operations
| Operation | Command / action |
|---|---|
| Tail logs | kubectl logs -n <ns> -f deploy/pricing |
| Re-seed a variant's fare | Re-emit its ProductVariant row (CDC RETRIEVE) — worker is idempotent |
| Inspect winning fare | POST /simulation-v2/calculate with the variant + context; read the fareSource on the PRICE applied-rule |
| Run migration manually | bun run migrate (in pod) — seeds permissions + role-permissions |
| Verify CDC consumption | Check consumer group lag for PRICING_CONSUMER_GROUP on PRODUCT_VARIANT |
DB writes / migrations are operator-run. Diagnose read-only via the calculate endpoints.
5. Related Pages
- Configuration
/runbook/— central runbook for cross-service incidents- Decisions