As our fintech platform scaled across Southeast Asia, our legacy Java-based authentication system began to show its age. What started as a simple solution for issuing tokens and handling logins became a bottleneck for feature development, security, and operational efficiency. Here’s how we migrated from our in-house authentication to FusionAuth, and what we learned along the way.
Our original authentication service was a Java-based system that handled user logins, token issuance, and basic 2FA. Over time, it became clear that:
- Feature development was slow: Adding new flows like SSO or advanced MFA took months of engineering effort.
- Security gaps emerged: Real-time threat detection, breach alerts, and device monitoring were missing.
- Maintenance was costly: Only a handful of engineers understood the system, and incidents were frequent.
- Scaling pains: Supporting hundreds of thousands of users across multiple countries led to technical debt and operational headaches.
The system was tightly coupled to our internal databases and required direct integration with our API gateways for access control. As our product suite grew, so did the complexity of managing user credentials, enforcing security policies, and supporting new authentication requirements. The lack of modern features such as adaptive MFA, passwordless login, and robust monitoring made it increasingly difficult to keep up with both regulatory demands and user expectations.
Recognising that authentication is not our core business, we proposed moving to a SaaS solution. Our goal was to find a platform that could not only match our current capabilities but also provide a foundation for future growth and security enhancements.
We evaluated several options (back in mid 2023, information may be outdated), comparing them across key factors:
Key:
- Price: Estimated monthly cost for 50,000 Monthly Active Users (MAU).
- MFA Support: Range and flexibility of multi-factor authentication options.
- Support & SLA: Availability of enterprise support and Service Level Agreements.
- Documentation & Ease of Use: Quality of docs and developer experience.
- Flexible Deployment: Managed cloud, self-hosted, or both.
A thorough technical evaluation confirmed that FusionAuth could support our migration strategy, including phased user migration, integration with our existing infrastructure, and future enhancements.
Migrating authentication systems is a high-stakes endeavour — any disruption can directly impact user experience and business operations. To minimise risk, we adopted a phased migration strategy, using FusionAuth as a data store behind our existing authentication service. This approach allowed us to keep our legacy auth service as the interface for all authentication requests while gradually shifting the underlying data operations to FusionAuth. By proxying requests and synchronising user data, we could validate the new system in production, catch issues early, and ensure a seamless experience for users.
Key tasks included:
- Repository Layer Refactoring: Implement additional Repo layer, instead of DB queries, use FusionAuth API calls.
- User Data Migration: Import credentials, MFA settings, and metadata to FusionAuth while preserving password hashes.
- API Gateway Integration: Supported both JWT (FusionAuth) and legacy tokens for gradual client transition.
- Parallel Operation: Legacy and new systems ran in parallel with our FusionAuth data serve as single source of truth.
The key to use FusionAuth as a data store is the repository layer refactoring. The original UserRepo was moved to UserPostgresRepo, with the new UserRepo containing both UserPostgresRepo and the newly implemented UserFusionAuthRepo . We are able to switch base on user’s migrated flag and dynamically to determine which repo to use when handling requests.
public class UserRepository {UserPostgresRepository postgresRepo;
UserFusionAuthRepository fusionAuthRepo;
public User findByUsername() {
User user = fusionAuthRepo.findByUsername(username);
if (user == null) {
user = postgresRepo.findByUsername(username);
}
return user;
}
public void updateUser(User user) {
if (user.isMigrated()) {
fusionAuthRepo.updateUser(user);
} else {
postgresRepo.updateUser(user);
}
}
}
public class UserFusionAuthRepository {
public User findByUsername(String username) {
// find user in FusionAuth with API calls
}
public void updateUser(User user) {
// update user in FusionAuth with API calls
}
}
public class UserPostgresRepository {
public User findByUsername(String username) {
// find user in legacy Postgres database
}
public void updateUser(User user) {
// update user in legacy Postgres database
}
}
At this point, both auth service and FusionAuth is able to hand out access tokens and clients are able to use either of them to get authenticated. This gave us the opportunity to migrate clients one by one at their own pace.
We then began updating clients to use FusionAuth directly.
- Documentation and Support: Created guides for engineering teams with clear integration steps.
- Backend Services Migration: FusionAuth Library was created and Services use the library to call FusionAuth directly.
- Frontend Migration: Design a common login experience and customise FusionAuth’s hosted login pages. Frontend clients redirected to FusionAuth to authenticate.
- Custom Flows: Implemented region and application specific MFA and SMS OTP with FusionAuth’s extensibility.
Given our limited dev resource and bandwidth, the whole migration process happened slowly over the span of a year.
With all clients migrated, we are able to finally stop the legacy auth service.
- Migrate Active Code: Some auth related feature like encryption endpoint are still active and migrated to other services.
- Resource Cleanup: Clean up the API gateway authentication rules and stop the auth service.
We achieved significant improvements:
- Reduced Maintenance: Legacy Java stack is gone; duplicated user data are now in a single place.
- Stronger Security: Multiple MFA options, breach alerts, and modern threat detection now built-in.
- Faster Development: Features like SSO and passwordless login can be enabled via config.
- Unified UX: Seamless login across all products and applications to improved user satisfaction.
- Cost Savings: Lower TCO and better allocation of engineering resources.
Some takeaways from the journey:
- Focus on Core Value: Delegating auth freed us to focus on our mission — empowering SMEs.
- Phased Migration Minimises Risk: The data-store approach enabled two systems to function at same time, this minimises the risk and provide greater flexibility for client migration.
- Maintain Project Oversight: While this approach gave clients the flexibility to transition at their own pace, it is equally important to maintain tight control over the project timeline to ensure timely delivery.
Migrating to FusionAuth was a complex but rewarding project. With careful planning, cross-team collaboration, and the right partner, we improved security, reduced operational burden, and laid a foundation for future growth.
For teams facing similar challenges, we recommend this migration strategy to keep both systems working so that clients can be migrated gradually. The incremental progress, can make auth modernisation achievable — and transformative.
.png)
