Skip to main content

Service Architecture

Peak Gateway runs 7 Kotlin/Spring Boot microservices on Google Cloud Run.

Service Map

ServiceLocal HTTPPurposeKey Dependencies
auth8181OAuth2 token issuance, JWK publishing, client adminschema, security, rate-limiting, Spring Authorization Server
processing8182Core payment engine: sale, auth, capture, void, refund, subscriptionstransit-client, schema, security, notifications, rate-limiting, resilience
management8183Portal backend: merchants, users, SAML SSO, reports, audit, device commandsschema, security, notifications, rate-limiting
online-txn8184E-commerce: checkout sessions, hosted payments, webhooks, API keystransit-client, schema, security, notifications, rate-limiting
merchant-onboarding8185CDE-scoped: TransIT credentials, NexGO XTMS device bindingtransit-client, xtms-client, schema, security, Cloud KMS, resilience
status8186Health aggregator (no database, no Pub/Sub)security only
card-present8187In-person acceptance boundary: terminal sale/auth, transaction sync, sync refundprocessing, schema, security, notifications, rate-limiting

Every service container listens on port 8080 in Cloud Run and Docker. The ports above are the local docker-compose.dev.yml host mappings.

Communication Flow

Auth ──JWK──> Public services validate OAuth tokens via JWK endpoint
Processing <──IAM── Management <──Firebase── Portal
Processing <──IAM── Online-Txn <──OAuth── Checkout/E-commerce
Processing <──IAM── Card-Present <──OAuth── Terminals / in-person flows
Merchant-Onboarding <──IAM── Management --> TransIT + XTMS
Status ──health──> All services

Two-tier security model:

  • Public-facing (auth, management, online-txn, card-present, status): Firebase Auth + OAuth2 via JWK
  • Internal-only (processing, merchant-onboarding): Cloud Run IAM only — no public access, no LB route

Shared Library Dependencies

Servicesecurityschematransit-clientxtms-clientnotificationsrate-limitingresilience
auth
processing
management
online-txn
card-present
merchant-onboarding
status

Tech Stack

LayerTechnology
LanguageKotlin 2.2.2, Java 25
FrameworkSpring Boot 4.0.5, Spring Security 7.0
DatabaseCloud Spanner (PostgreSQL dialect) via SQLDelight 2.2.1
AuthOAuth2 (Spring Authorization Server) + Firebase Auth + SAML SSO
MessagingCloud Pub/Sub (email, SMS, transaction events)
External APIsTSYS TransIT Multipass (payments), NexGO XTMS (devices)
BuildBazel with rules_kotlin 2.2.2
DeploymentGCP Cloud Run (us-east1)
ObservabilityStructured ECS logging, OpenTelemetry -> Cloud Trace

Environments

EnvironmentAPI DomainPortalCloud Run Prefix
Productionapi.peakgateway.coportal.peakgateway.cogateway-{service}
Stagingstaging-api.peakgateway.costaging-portal.peakgateway.cogateway-{service}-staging

Request Flow

  1. Client sends request with Bearer token (OAuth2 or Firebase ID token)
  2. Cloud Run routes to the target service
  3. Security filters validate the token via JWK endpoint (auth service)
  4. Controller checks @RequireScope (API clients) or @RequireRole (portal users)
  5. Service layer executes business logic
  6. Repository layer queries Cloud Spanner via SQLDelight/PGAdapter
  7. External calls to TransIT/XTMS if needed
  8. Response wrapped in ApiResponse<T> envelope