Skip to content

Operations

1. Deployment

PropertyValue
Imageregistry/nx-seller-inventory:<tag>
Container Port3000
External Port31050
Snowflake ID5
Replicas (default)1 (dev) / 2+ (staging+)
Resources (req/lim)100m / 500m CPU, 256Mi / 1Gi memory
HPA targetCPU 70% (when scaled)
Migration modeRUN_MODE=migrate job before rollout; on-boot for dev
Live probeGET /v1/api/inventory/healthz
Ready probeGET /v1/api/inventory/readyz
Graceful shutdownSIGTERM/SIGINT → close Kafka producer + consumer (isForce=false)

Traefik routing labels

yaml
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.inventory.rule=PathPrefix(`/v1/api/inventory`)"
  - "traefik.http.services.inventory.loadbalancer.server.port=3000"

Required infrastructure

DependencyWhy
PostgreSQLPrimary datastore (schema inventory)
Kafka brokersMandatory — service refuses to start if APP_ENV_KAFKA_BROKERS empty
DebeziumRequired for CDC topics (MERCHANT, PRODUCT_VARIANT)
RedisOptional — auth cache; service starts without it
@nx/identity reachableJWKS verification on every JWT

2. Observability

SignalSourceWhere to look
Logsstdout (IGNIS structured logger, key: %s format)kubectl logs deploy/inventory / Loki
HealthGET /v1/api/inventory/healthz, GET /readyzGateway portal
OpenAPI live specGET /v1/api/inventory/doc/openapi.jsonGateway portal explorer
MetricsTraefik gateway :30800 (Prometheus scrape)Grafana — gateway dashboard
Kafka lagKafka cluster broker / BurrowTBD

Key log fields

FieldSourceNotes
requestIdheader X-Request-IdPropagated cross-service
userIdJWT subject
merchantIdrequest scope
topic / partition / offsetKafka consumerLogged on every message
referenceType / referenceIdinventory tracking writesFor audit trail correlation

Useful log search queries

QuestionQuery
Stock deduct failures (oversell-blocked)note=OVERSELL_BLOCKED
Re-deliveriestopic=payment.success AND idempotent skip
PO emit failuresKafka emit failed AND topic=purchase-order.received

3. Security

ConcernMitigation
AuthNJWT (ES256, JWKS pulled from identity at boot + on-demand)
AuthZCasbin via PolicyDefinitionService; permissions cached in Redis (or in-memory if Redis disabled)
Service-to-serviceBASIC strategy (commerce → inventory direct calls in shared TX)
SecretsK8s Secret mounted as env (APP_ENV_DB_URL, APP_ENV_KAFKA_SASL_PASSWORD, etc.) — never in code
TLSTerminated at Nginx → Traefik → service in plaintext (intra-cluster)
Rate limitTraefik middleware (default 100 rps/IP)
Network policyCilium — allow only gateway + Kafka + Postgres + Redis + identity (JWKS)
Soft-deletedeletedAt — no hard-delete by default; InventoryTracking immutable
IdempotencyAll Kafka handlers idempotent — safe under at-least-once delivery

4. Runbook

4.1 Alert classes

AlertTriggerCheckFixEscalate
InventoryHighErrorRate5xx >5% over 5mkubectl logs deploy/inventory | grep level=errorIdentify failing endpoint; restart if stuckon-call backend
InventoryKafkaLagConsumer group lag >10k on any topicBurrow / Kafka admin toolsScale replicas if CPU-bound; check handler errorson-call SRE
InventoryDBConnectionExhaustedpool exhausted errorspg_stat_activityBump APP_ENV_DB_POOL_MAX; check long-running TXon-call backend
InventoryStockNegativequantityOnHand < 0 rows in DBRun reconciliation queryAudit InventoryTracking for cause; manual adjustmenton-call backend + finance
InventoryOversellSpikenote=OVERSELL_BLOCKED count risingLog searchCheck sale order patterns; consider raising allowOversell for fast-moving itemson-call business + backend
InventoryPOEmitFailurepurchase-order.received emit log errorsGrep logsManual replay job; verify Kafka cluster healthon-call SRE

4.2 Common operations

OperationCommand
Tail logskubectl logs -n <ns> -f deploy/inventory
Run migrations manuallykubectl exec -it deploy/inventory -- bun run migrate
Reset Kafka consumer offsetUse Kafka admin: kafka-consumer-groups --reset-offsets --group SVC-00050-INVENTORY_CONSUMER_GROUP --topic <topic> --to-earliest --execute
Replay a PAYMENT_SUCCESS for a single orderManually re-emit message with same key from sale; idempotency lookup will skip if already processed
Force re-seed permissionsBump migration version + re-run migrate
Inspect stock for an item across locationsSELECT * FROM "InventoryStock" WHERE inventory_item_id = '...' AND deleted_at IS NULL;
Audit movements for a SaleOrderSELECT * FROM "InventoryTracking" WHERE reference_type = 'SALE_ORDER' AND reference_id = '...';

4.3 Recovery scenarios

ScenarioRecovery
Service crash mid-handlerKafka offset NOT committed → message re-delivered on restart; idempotency lookup skips already-processed entries
DB transaction succeeded, Kafka emit failed (PO receive)Log records the failed emit; manual replay tool publishes from PurchaseOrder snapshot
Wrong stock count detected(1) Pause sale traffic, (2) run cycle count via InventoryTicket type=CYCLE_COUNT, (3) write ADJUSTMENT_NEUTRAL tracking rows
Lost merchant default locationRe-emit Merchant CDC event → ensureDefaultLocation recreates

5. Cross-Service Runbook

For incidents that span multiple services, see central runbook/:

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.