Refactoring Auth, Not Breaking Prod: A Case Study in S2S Migration
What it takes to migrate from one identity manager to another without downtime — and how we pulled it off at CARS24.
At CARS24, scale isn’t just a goal — it’s a reality. And with scale comes complexity. As our internal ecosystem of services grew, so did the challenges in our authentication layer. This is how we moved from FusionAuth to a unified, in-house identity system built over Keycloak to power secure, scalable, and flexible service-to-service (S2S) communication. The ask was simple:
- Zero downtime
- Backward compatibility
- Easy adoption across services
- Future-ready architecture
And we did just that.
This post describes how we achieved a frictionless, production-safe migration — from design decisions to rollout strategy.
The Existing Setup
In our current setup, every internal service communicates with external systems via Synapse, as shown in Figure 1. Synapse is our gateway that monitors and validates requests. To authenticate these requests, we relied on FusionAuth. Each service had its credentials, configured via environment variables and used to fetch tokens.
Tokens (JWT tokens) generated by FusionAuth were attached to requests (in headers) and validated by Synapse before being passed on. The setup worked fine.
We built a library named auth-lib. It is added as a dependency in the internal services. Auth-lib’s sole purpose is to generate a token via FusionAuth. The flow is shown in Figure 2.
Why Move Away from FusionAuth?
As CARS24 scaled, so did our microservices and auth demands. Here’s what we started noticing:
- Different teams used different providers — FusionAuth, Okta, DeScope — creating inconsistencies and security blind spots.
- Client Credentials Grant wasn’t supported in the open-source version.
- FusionAuth, being a third-party service, meant limited control and opaque debugging.
- We lacked fine-grained authorisation; any internal service could hit any external one.
- Licensing and feature gating became blockers for horizontal scalability.
New Flow, Familiar Feel
Because of the above challenges, we needed to migrate from FusionAuth.
We needed a control centre — something that unified authentication, gave us visibility, and offered extensibility. So we leaned into something we already trusted internally: UMS, our Keycloak-based authentication platform.
With UMS, we moved toward a token-driven S2S auth flow we owned, extended, and customised — without hitting a paywall.
While the infrastructure changed under the hood, the surface-level service experience stayed the same, intentionally.
Let’s break it down:
- An internal service receives a request.
- It uses auth-lib to fetch a token using its credentials.
- Previously, auth-lib would call FusionAuth to generate a JWT.
- That token was added as an Authentication header and sent to Synapse.
- Synapse validated the token and forwarded the request to the appropriate external service.
We preserved this structure, but swapped out FusionAuth with UMS behind the scenes.
Technical Strategy
To make the transition painmigrate a core infrastructure componentless for our internal services, we made surgical improvements:
- auth-lib was updated to support token generation using UMS.
- Synapse now uses both FusionAuth and UMS to validate the token.
We knew all services wouldn’t update overnight. So, we added a factory-based validator in Synapse.
IF token.issuer IS "fusionauth" THEN call validateWithFusionAuth(token) ELSE IF token.issuer IS "ums" THEN call validateWithUMS(token) END IF
How did this help the migration?
- The token generation logic is in the auth-lib library, meaning no dependency on internal services.
- The token validation part now allows both old and new tokens to coexist, with no downtime, no disruption.
Action Items for Internal Services
Internal services had to do just two things:
- Upgrade the auth-lib dependency to the latest version.
- Update environment credentials.
That’s it. No API rewrites. No cascading changes. Adoption was quick and clean.
Engineering Wins from the Migration
This wasn’t just a provider swap — it was an opportunity to tighten up our architecture:
- Pluggable Token Generators in auth-lib. Easily switch auth sources with one SDK upgrade.
- Dynamic Token Validators in Synapse. Support both old and new tokens, determined at runtime.
- Separation of Responsibilities. Token creation and validation are in separate components.
- Unified Credential Handling. Replaced hardcoded FusionAuth credentials with centralised UMS config.
- Ready for Authorisation. We’ve laid the groundwork to restrict which services can talk to which others.
Lessons Learned
- Don’t reinvent the flow — refactor under the hood. Developers love familiarity. Keeping the token flow identical made adoption easy.
- Design with coexistence in mind. Supporting both FusionAuth and UMS during the transition helped avoid downtime and pressure.
- Loose coupling = easier upgrades. By abstracting token generation and validation, we enabled future migrations with minimal change.
Final Thoughts
We didn’t migrate to a new identity platform — we transitioned from one to another. But we did it with:
- Zero downtime
- Full backward compatibility
- Minimal lift for internal teams
And now, we’re ready for the future — with centralised authentication, precise control, and the foundation for fine-grained authorisation.
From FusionAuth to UMS — not a rebuild, just a better way forward.
Loved this article?
Hit the like button
Share this article
Spread the knowledge
More from the world of CARS24
Navigating AWS Service Migration: Challenges and Lessons Learned
A recent audit compliance reasons forced us to migrate NBFC tech to a separate account, ensuring clear data ownership, proper segregation, and controlled data sharing with other entities.
Chaos to Clarity: How We Built a Scalable Observability System for Logs, Metrics and Traces
This blog focuses on how we built our Observability Stack at CARS24, which includes Monitoring, Logging, and Tracing, to gain insights about our deployed services and receive instant alerts when something unexpected happens.
Building Asynchronous ML Inference Pipelines with Knative Eventing and KServe
The combination of modern cloud-native technologies like Kubernetes, Knative Eventing, and KServe provides a robust foundation for building adaptable machine learning infrastructure.