Skip to content

Deployment

The gateway runs as a containerized service. The Salesforce spike is the template for the first connector.

Container Layout

gateway/
├── connectors/
│   ├── salesforce/      # our SF client, our JWT auth, our field mappings
│   ├── payments/        # our payment provider client
│   ├── partners/        # our dining, hotels, etc.
│   └── databases/       # our direct DB access
├── auth/                # our consumer auth (API key, mTLS)
├── ratelimit/           # our per-consumer, per-resource
├── retry/               # our bounded retry, our circuit breaker
├── webhooks/
│   ├── inbound/         # our resources → our gateway
│   └── outbound/        # our gateway → our consumers
├── observability/       # our tracing, our logging, our metrics
├── schemas/             # our JSON schemas for validation
├── test/
│   ├── unit/
│   └── integration/
├── Dockerfile
└── package.json

The spike's src/ layout is the starting point for the connectors/salesforce/ directory. The spike's top-level server.js becomes the gateway's main entry point that wires all connectors together.

Dockerfile

  • Multi-stage build
  • Production stage uses node:20-alpine (or current LTS)
  • Runs as non-root user
  • Health check baked in: HEALTHCHECK CMD wget -qO- http://localhost:3000/v1/healthz
  • No secrets in the image; injected at runtime

Replicas

  • 2+ gateway replicas in production
  • Stateless (after auth, any request can hit any replica)
  • Behind a load balancer
  • The JWT token cache lives in Redis so replicas share tokens

Health & Readiness

  • /v1/healthzliveness, always returns 200 if the process is up
  • /v1/statuszreadiness, returns 200 only if all resource connections are healthy
  • Platform uses these for k8s probes

CI/CD

Pipeline stages:

  1. Lint
  2. Unit tests
  3. Integration tests (against our SF sandbox, partner sandboxes)
  4. Build container
  5. Push to registry
  6. Deploy to staging
  7. Smoke tests against staging
  8. Manual approval for prod
  9. Deploy to prod

Cloud

The gateway is cloud-agnostic. Production target is whatever the rest of Atlantes runs on. The service has no application state, so any container host works (ECS, Cloud Run, k8s, Fly, etc.).

Configuration

All config via environment variables. Required at boot:

PORT=3000
LOG_LEVEL=info
REDIS_URL=...

# Per-resource config
SALESFORCE_LOGIN_URL=https://login.salesforce.com
SALESFORCE_CLIENT_ID=...
SALESFORCE_USERNAME=...
SALESFORCE_PRIVATE_KEY_SECRET_REF=...

# Per-consumer config (or stored in DB and loaded at startup)
CONSUMER_ATLANTES_KEY_SECRET_REF=...
CONSUMER_ATLANTES_SECRET_SECRET_REF=...

Secrets are resolved from Doppler on startup. The gateway refuses to start if any required secret is missing.

Marchay Platform Documentation