ADR-004: Use Gravitee as Internal API Gateway
| Field | Value |
|---|---|
| Status | Accepted |
| Date | 2026-04-07 |
| Related SAD | SAD-001 |
| Related ADR | ADR-001 |
Context
The xRED ELN integration layer sits behind MuleSoft (the external gateway mandated by LEM). Once traffic enters the Roche Corporate Network, it needs to reach individual integration services running on Minerva (EKS). The question is whether each service should handle its own authentication, rate limiting, caching, and routing — or whether a shared internal gateway should sit in front of them.
ORCA (the platform team) uses a custom NGINX gateway for this role, but with limited capabilities (basic path routing and rate limiting only).
Decision
Use Gravitee, the API gateway managed by the Minerva platform, as the single internal entry point for all xRED ELN integration services within the RCN.
All traffic from MuleSoft enters through Gravitee before reaching any application service. Services are not exposed directly — they are only reachable via Gravitee-managed API definitions.
Note: each Minerva deployment also includes a default NGINX ingress controller as part of the Kubernetes infrastructure. NGINX handles TLS termination and ingress routing at the cluster level. Gravitee sits above NGINX as the application-level API gateway — it is where authentication, caching, rate limiting, and API management happen. The two are complementary, not competing:
MuleSoft → Gravitee (API management) → NGINX Ingress (K8s routing) → Service PodRationale
Centralised authentication
Gravitee handles authentication validation at the gateway level. Services behind it receive pre-validated requests and do not need to implement their own auth middleware.
This is especially important because of a Signals platform limitation: for External Data
integrations (Lists, Tables, Chemical Sources), Signals sends only a single
Authorization header (Basic Auth) plus an optional client certificate. There is no
support for OAuth, bearer tokens, or custom headers. This single credential is consumed by
the MuleSoft → Gravitee chain for transport-level authentication — it cannot be passed
through to backend services for business-level auth. Gravitee absorbs this constraint at
the gateway, so individual services do not need to deal with it at all.
In practice:
- Lookups (External Data): Gravitee validates incoming requests using a Groovy policy
script that checks
Authorization: Basiccredentials (the MuleSoft proxy identity). The service receives only authenticated traffic and focuses purely on data transformation. - Apps (External Actions): External Actions involve a browser redirect, so richer auth is possible (dual OAuth via Janus + Signals). Gravitee can still enforce policies before forwarding to the application layer.
- New services get authentication for free by registering an API definition in Gravitee.
This is a significant reduction in per-service complexity. Each adapter only needs to implement business logic — not security plumbing.
Response caching
Gravitee provides built-in response caching at the gateway level. For External Data integrations (Lookups), where Signals polls the same endpoints repeatedly:
- Frequently requested reference data (compound lists, project dropdowns) can be cached at the gateway without any application-level caching code.
- Cache TTLs are configured per API definition, not per service deployment.
- Cache invalidation is managed centrally, reducing the risk of stale data in individual services.
This is especially valuable given Signals’ External List refresh pattern — Signals polls on a schedule (hourly/daily), but multiple Signals tenants or concurrent users may hit the same endpoint within seconds.
Rapid prototyping and POC for new services
Gravitee’s API definition model allows new integration services to be exposed quickly without infrastructure changes:
- A new service is deployed to Minerva as a Kubernetes deployment.
- A Gravitee API definition is created pointing to the service’s internal K8s address.
- The service is immediately accessible through the existing MuleSoft → Gravitee path.
- No NGINX configuration, no ingress controller changes, no DNS updates.
This makes it trivial to stand up proof-of-concept services for evaluating new integrations before committing to a full production setup. A developer can deploy a FastAPI adapter and have it reachable from Signals within minutes.
Centralised rate limiting
The Signals platform has a tenant-wide quota of 1,000 API calls per minute. Gravitee provides rate limiting at the API definition level, allowing the team to:
- Protect individual backend services from traffic spikes.
- Allocate rate budgets per integration (e.g., 200 calls/min for lookups, 100 for apps).
- Monitor and adjust limits without redeploying services.
This complements MuleSoft’s external rate limiting with internal traffic shaping.
Observability and analytics
Gravitee provides centralised API analytics — request counts, latency percentiles, error rates, consumer breakdown — across all integration services from a single dashboard. This gives the team visibility into:
- Which integrations are most heavily used.
- Which upstream systems are slow or failing.
- Traffic patterns that inform scaling decisions.
Without a gateway, this data would need to be aggregated from individual service logs.
Managed by Minerva
Gravitee is provisioned and maintained by the Minerva platform team. The xRED team does not need to operate, patch, or scale the gateway infrastructure. This is a significant operational advantage over self-managed alternatives like NGINX or Envoy.
Alternatives Considered
Direct service exposure (no internal gateway)
Rejected. Each service would need to implement its own authentication, rate limiting, and caching. This duplicates effort across every adapter, increases the attack surface, and makes it harder to enforce consistent security policies.
NGINX-only gateway (ORCA’s approach)
Considered. ORCA uses a custom NGINX as their sole API gateway, routing based on query parameters. While simple, it provides only basic path routing and rate limiting — no caching, no auth validation, no analytics, and requires manual configuration for each new service. Note that xRED already has NGINX as part of Minerva’s default ingress — the question is whether NGINX alone is sufficient or whether Gravitee adds value on top. It clearly does: auth, caching, analytics, and API management are capabilities NGINX ingress does not provide.
Envoy / Istio service mesh
Rejected as overkill. A full service mesh adds significant operational complexity (sidecar injection, mTLS management, control plane operation) that is not justified for the current number of services. Gravitee provides the needed gateway capabilities without the mesh overhead.
Consequences
- All services must be registered as Gravitee API definitions — no direct exposure.
- The team depends on Minerva’s Gravitee availability and SLA.
- Gravitee configuration becomes part of the deployment process (API definitions must be created/updated alongside K8s manifests).
- Debugging requires checking both Gravitee logs and service logs — an additional layer to inspect when diagnosing issues.
- Caching at the gateway level means services may not see all incoming requests — this is intentional but must be accounted for in monitoring and debugging.
- New services get auth, caching, rate limiting, and analytics without writing any infrastructure code.