Skip to main content

Billing Service — Service Overview

Status: populated Owner: Platform Engineering + Finance Last updated: 2026-04-18 Companion: DOMAIN_MODEL · API_CONTRACTS · EVENT_SCHEMAS · ADR-0001 Kong

1. Purpose

billing-service is the authoritative source of truth for revenue, margin, and invoicing in Ghasi-SMS-Gateway. It:

  • Consumes billing.events from NATS JetStream (produced by dlr-processor) to record per-message chargeable events.
  • Applies versioned pricing rules — per-segment or flat-per-message — keyed by (accountTier, operatorId, direction, currency).
  • Models operator costs alongside customer pricing to compute per-message margin.
  • Generates monthly invoices via a scheduled cron: PDF rendered from templates, stored in S3-compatible object storage.
  • Exposes an admin/internal REST API (via Kong) for pricing CRUD, operator cost CRUD, invoice list/download, and usage queries.
  • Publishes billing.invoice.generated NATS event after each invoice is finalized.

2. Bounded Context

Revenue & Finance — authoritative owner of all monetization data. Classified as Core (financial correctness is a business-critical requirement; incorrect billing directly affects revenue and contractual SLAs).

3. Responsibilities

AreaWhat billing-service owns
Chargeable event ingestionConsumes billing.events, stores billing_events, deduplicates via messageId
Pricing engineResolves applicable pricing_tables row; computes customerPrice per message/segment
Operator cost trackingResolves operator_costs row; computes operatorCost; derives margin
Usage aggregationIncrements usage_summaries (hourly/daily buckets) for query efficiency
Invoice generationMonthly cron: aggregates usage, renders PDF, stores to S3, persists invoices record
Invoice publicationPublishes billing.invoice.generated NATS event post-persist
REST APIPricing CRUD, operator cost CRUD, invoice list/download, usage query (admin/internal, via Kong)
Multi-currency supportUSD default; currency field on pricing_tables; FX rate applied at event time
Pricing cacheRedis TTL-60s cache for hot pricing lookups

4. Non-Responsibilities

AreaOwner
DLR correlation and event productiondlr-processor
SMS send decision / routingsms-orchestrator + routing-engine
Customer-facing invoice UIcustomer-portal (reads via API)
Payment collection / card processingExternal payment gateway (future)
Webhook delivery to customerswebhook-dispatcher
Auth enforcement at KongKong + auth-service

5. Dependencies

DependencyKindPurpose
NATS JetStream (billing.events)Event bus (consumer)Ingest chargeable events from dlr-processor
NATS JetStream (billing.invoice.generated)Event bus (producer)Notify downstream on invoice finalization
PostgreSQL (schema billing)Data storeAll billing tables
RedisCachePricing lookup cache, TTL 60s
S3-compatible object storeStorageRendered invoice PDFs
Kong GatewayUpstream (HTTP)Proxies admin/internal REST API
auth-serviceHTTP (via Kong headers)JWT claims for account/tenant context

6. High-Level Flow

7. Key Design Decisions

DecisionRationaleTrade-off
Idempotent event ingestion on messageIdPrevents double-billing on NATS redeliveryRequires PG INSERT ... ON CONFLICT DO NOTHING
Versioned pricing_tables (not point-in-time snapshot)Allows retroactive pricing corrections within a billing period for agreed adjustmentsMust specify effectiveFrom/effectiveTo carefully
Redis pricing cache (TTL 60s)Pricing lookups are hot and read-heavy; avoids PG pressure60s stale window acceptable; pricing changes are rare
Usage summary pre-aggregationInvoice generation queries pre-aggregated buckets rather than raw event tableExtra write on ingest; saves order-of-magnitude on invoice query
Monthly cron invoice, not real-timeStandard B2B billing cadence; simplifies deferred FX ratesCustomers cannot self-serve mid-month subtotals easily (usage query API bridges this)
S3 PDF storage, not PG BYTEAPDF sizes (100 KB–5 MB); keeps PG leanRequires S3 availability for download; presigned URL approach avoids proxy

8. Status

Design approved. Implementation gated on dlr-processor publishing billing.events (see EVENT_SCHEMAS) and S3 bucket provisioning. See SERVICE_READINESS for gate checklist.