Skip to main content
Back to case studies

Case study

Intelligence data platform

Building the API that connected the team's services for a replacement platform.

API architecture / YARP / Bruno / Service integration

Initial condition and responsibility

The predecessor failed frequently and did not meet operational requirements. I architected the replacement API to integrate services developed by other members of the team.

The team retained working code and reduced it to the replacement's requirements. My implementation included YARP passthroughs, controller overrides, GraphQL integration, token-handling middleware and WebSocket streaming.

Routing and integration architecture

YARP handled operations that could preserve the upstream contract, avoiding duplicate controllers and response models for vendor endpoints.

Specific controller routes implemented application validation and orchestration. Location searches, for example, required input checks and request limits before dispatch; adjacent operations remained available through catch-all routes.

API request paths

Caller request endpoint routing the selected handling path

  • YARP passthroughResolve the external API, remove client-supplied managed credentials, attach server-managed credentials and stream to the upstream.
  • Controller overrideRun application-owned validation or orchestration, acquire the required credentials and dispatch the operation.
  • GraphQL gatewayUse the composed schema to plan queries across the participating service subgraphs.
These are alternative request paths. A request does not pass through all three. The diagram shows responsibilities rather than every middleware component or deployment boundary.

Vendor-specific strategies handled upstream authentication protocols. A shared token service provided caching and coordinated renewal. Proxy middleware replaced client-supplied managed headers with server-managed credentials. Controller operations used a separate dispatch path.

ASP.NET Core Data Protection protected cached token values, reducing plaintext retention. Credentials remained accessible to the running application when required for authentication.

GraphQL federation

GraphQL federation provided a single query entry point across participating services. The composed schema defined distributed query planning, reducing service coordination in client applications.

Changes to participating schemas required updates to the composed gateway package. WebSocket streaming introduced separate connection-lifecycle requirements alongside request-response operations.

Error response policy

Local validation and credential-acquisition failures could return Problem Details with a trace identifier. Transparent passthroughs preserved upstream statuses and bodies, including errors.

A preserved upstream rejection supplies information required by the caller. For example, 429 may represent temporary rate limiting or exhausted quota, requiring different retry decisions. The proxy-boundary note covers response and telemetry policy.

Integration verification

Initial proof-of-concept checks used Bruno to exercise passthroughs and controller endpoints through the token-handling middleware. Subsequent integration connected the team's services in a shared development deployment.

Controlled-upstream integration tests inspect request targets, credential replacement, cursor forwarding, cancellation and upstream error propagation. These checks exercise routing and middleware beyond direct controller tests.

Related implementation detail: credential renewal under concurrency.

Outcome

The replacement API integrated service queries, upstream passthroughs and application-specific operations through distinct handling paths. It supported the team's delivery of the second SaaS version. My responsibility covered API architecture and integrations.

Related notes: testing at application boundaries and making dependency boundaries explicit.

This account describes my contribution at a sanitised level. Operational details and identifying information are omitted.

← Back to case studies