Identity in high-velocity environments is a moving target. Teams that ship daily quickly discover that a monolithic user profile—one blob of claims, roles, and metadata—becomes a bottleneck. Every change to the profile schema requires coordinated releases across services, and the blast radius of a single attribute error expands to every consumer. This guide describes a modular identity architecture: decomposing the concept of 'self' into independently versioned, loosely coupled modules. We focus on the protocol—the contracts, gateways, and synchronization patterns—that keeps these modules coherent without reintroducing the coupling they were meant to avoid.
This is written for identity architects and platform engineers who already understand OAuth, OIDC, and basic claims-based identity. We skip the primer on why identity matters. Instead, we go straight to the trade-offs: when to split, how to route, and what breaks first.
Where Modular Identity Shows Up in Real Work
The need for modular identity often emerges from a concrete pain: a single user record that serves both a mobile app and an internal admin tool, but the admin tool needs different claims (department, clearance level) that the mobile app must never see. A naive solution is to add a 'role' field and filter on the client side, but that leaks data and creates coupling. A modular approach splits the identity into separate claim sets—one for public-facing context, one for internal—each governed by its own policy and issued by a different authority.
Another common scenario: a company acquires a product with its own user store. The integration team faces a choice—migrate all users to the corporate IdP (months of work, high risk) or federate identities across two systems. Modular identity architecture provides a third path: define a canonical identity bus where each system publishes its claims as modules, and the consuming services subscribe only to the modules they need. This reduces migration pressure and allows each system to evolve its user model independently.
In practice, we see this pattern most often in platform engineering teams that support multiple product lines. A single login session might need to carry claims from a CRM module, a billing module, and a compliance module. Each module has different latency requirements, refresh cadences, and trust levels. Treating them as a single token payload forces every module to be refreshed together, wasting bandwidth and exposing all claims to every service. The modular protocol issues separate tokens or claim bundles, each scoped to the services that actually need them.
A third example comes from regulatory environments. GDPR requires that personal data be stored with clear purpose limitation. A monolithic identity store makes it hard to prove that 'profile data used for analytics' is separate from 'profile data used for authentication.' Modular identity architecture enforces separation at the data model level: the authentication module holds only the minimal claims needed for login; the analytics module holds aggregated, anonymized identifiers. This architectural boundary becomes an auditable control.
The common thread across these scenarios is velocity. When teams can change their part of the identity model without coordinating with every other team, release cycles shrink. The modular protocol is the set of rules that makes this safe: versioned schemas, explicit dependency declarations, and circuit breakers when a module becomes unavailable.
Signs Your Environment Is Ready for Modular Identity
Not every team needs this complexity. The following indicators suggest that a monolithic model is already causing friction: (1) identity schema changes require multi-team code reviews and coordinated deployments; (2) a single attribute error (e.g., a misformatted email) breaks multiple downstream services; (3) teams are caching user data locally because the central profile service is too slow or too broad; (4) compliance audits ask for data flow diagrams that show personal data crossing boundaries you didn't intend. If you see two or more of these, modular identity is worth evaluating.
Foundations Readers Confuse
A common misunderstanding is that modular identity is the same as multi-tenant identity. Multi-tenancy is about isolating data between customers; modular identity is about isolating claims within a single user's identity. They can coexist—a modular system can be multi-tenant—but they solve different problems. Another confusion: modular identity versus attribute-based access control (ABAC). ABAC is a policy model; modular identity is a data architecture. You can implement ABAC on top of a modular identity bus, but the modularity is about how claims are stored and distributed, not how they are evaluated.
Another frequent error is equating modular identity with microservices identity. Microservices identity often focuses on service-to-service authentication (mTLS, JWTs between services). Modular identity, as we define it, is about the user's identity being composed of independently managed parts. A microservice may consume multiple identity modules, but the modules themselves are not microservices—they are logical claim sets with their own lifecycle.
Perhaps the most dangerous confusion is thinking that modular identity means 'no central identity store.' In most implementations, there is still a core identity hub that holds the minimal stable attributes (user ID, primary email, account status). The modules are satellites that extend the identity with context-specific claims. The hub provides the anchor; the modules provide the flexibility. Without the hub, you lose the ability to correlate claims from different modules to the same user, and you end up with a fragmented identity that is hard to revoke or audit.
What Modular Identity Is Not
To avoid over-engineering, it helps to define what this approach is not. It is not a replacement for a well-designed OIDC provider. The OIDC provider still issues the core ID token and access token. Modular identity adds a layer above: the ability to attach additional claim modules that are fetched or resolved lazily, rather than bundled into every token. It is not a free pass to skip security reviews. Each module introduces a new trust boundary and new attack surface—especially if modules are served by different teams or external systems. It is not a performance optimization for small-scale systems. For a single application with fewer than 10,000 users and a simple role model, a monolithic profile is simpler and faster.
Patterns That Usually Work
After observing several implementations, three patterns consistently deliver value. The first is the claim gateway: a single endpoint that accepts a user's session token and returns a list of available claim modules. The gateway does not store claims; it routes requests to the appropriate module based on the session's scope. This pattern works well when modules are owned by different teams and need to be deployed independently. The gateway becomes the contract boundary—each module registers its claim types and version with the gateway, and consumers discover modules dynamically.
The second pattern is lazy claim resolution. Instead of bundling all claims into the authentication token, the token contains only a user ID and a set of module pointers. When a service needs a specific claim (e.g., 'department'), it calls a module endpoint with the user ID and receives the claim value. This pattern reduces token size, limits exposure of sensitive claims, and allows modules to be updated without reissuing tokens. The trade-off is increased latency for the first claim request and the need for a caching strategy.
The third pattern is versioned claim schemas. Each module publishes a schema (using something like JSON Schema or Protobuf) with a version number. Consumers declare which version they support, and the module serves the appropriate schema version. This allows the module owner to evolve the claim structure without breaking existing consumers. When a consumer is ready to upgrade, it updates its declared version. This pattern is essential in high-velocity environments where teams ship weekly.
When to Use Each Pattern
The claim gateway is best when you have more than three distinct claim sources and the sources are owned by different teams. Lazy claim resolution is ideal when claim values are large, sensitive, or rarely accessed. Versioned schemas are non-negotiable if you have external consumers or if your release cadence is faster than two weeks. A common mistake is to implement all three patterns at once. Start with one—usually the claim gateway—and add the others as friction points emerge.
Anti-Patterns and Why Teams Revert
The most common anti-pattern is the over-split: decomposing identity into so many modules that a single user request triggers ten module calls to assemble a basic profile. Teams that over-split often do so because they think 'every attribute should be its own microservice.' The result is high latency, complex error handling, and a debugging nightmare. The fix is to group claims that change together and are consumed together into a single module. A good heuristic: if two claims are always requested in the same API call, they belong in the same module.
Another anti-pattern is shared mutable state between modules. For example, a 'profile' module and a 'preferences' module both update the user's display name. When the two modules have different update frequencies, the display name becomes inconsistent. Teams often revert to a monolithic store because they cannot keep the modules synchronized. The solution is to designate a single module as the authoritative source for each claim and enforce that other modules read-only. If a claim needs to be writable from multiple contexts, introduce a write-back protocol that publishes events to a central bus.
A third anti-pattern is ignoring module lifecycle. Modules that are never deprecated accumulate stale claims that confuse consumers. Teams revert because the module inventory grows unmanageable. The discipline is to treat each module as a product: it must have an owner, a deprecation date, and a migration plan. If a module has no consumers for six months, it should be retired. This requires telemetry on claim usage—something many teams skip until the module count becomes unmanageable.
Why Teams Revert to Monolith
In the projects we've observed, the decision to revert is rarely because modular identity is theoretically wrong. It is because the operational cost of maintaining the module contracts, the gateway, and the synchronization logic exceeds the benefit of independent deployability. This usually happens when the team size is small (fewer than five engineers) and the identity model is stable. For a small team, the overhead of a module registry, version negotiation, and cross-module debugging is not worth the flexibility. The recommendation is to start modular only when you have at least two teams touching identity or when the identity schema changes more than once per quarter.
Maintenance, Drift, and Long-Term Costs
Modular identity architecture has a maintenance profile that surprises many teams. The most significant cost is schema drift: over time, modules evolve independently, and the relationships between claims become implicit rather than explicit. A user's 'role' in the billing module might mean something different from 'role' in the support module. Without a cross-module dictionary, consumers make assumptions that eventually break. The mitigation is to maintain a shared ontology—a document that maps each claim across modules and defines its semantics. This ontology must be versioned and reviewed quarterly.
Another long-term cost is latency creep. As more modules are added, the average time to resolve a full identity increases. Teams compensate by caching more aggressively, but caching introduces staleness. The solution is to set explicit latency budgets per module and to monitor p95 resolution times. When a module exceeds its budget, the team must optimize or the module must be merged into a faster module. Without this discipline, the system becomes slower than the monolith it replaced.
Audit complexity also grows. In a monolith, a single query can show all claims for a user at a given time. In a modular system, reconstructing the user's identity state requires querying each module's history and reconciling timestamps. This is a problem for compliance teams that need to answer 'what data did we have about this user on this date?' The workaround is to maintain an audit log that captures the output of each module resolution, but this log itself becomes a large data store. Teams should budget for audit infrastructure from the start.
Cost of Coordination
Even with good contracts, cross-module changes require coordination. If a module changes its claim type from string to array, every consumer that reads that claim must update. The versioned schema pattern reduces the frequency of breaking changes, but it does not eliminate them. Each breaking change requires a migration window where both old and new consumers are supported. This coordination overhead is often underestimated. A rule of thumb: if your team spends more than 20% of its identity-related effort on cross-module coordination, consider merging some modules.
When Not to Use This Approach
Modular identity is not a default choice. It adds complexity that is justified only in specific conditions. The first condition is team topology: you need at least two independent teams that own different parts of the identity model. If one team owns all identity-related code, a modular architecture adds overhead without benefit. The second condition is change velocity: the identity schema changes more than once per quarter. If the schema is stable for years, the flexibility of modules is wasted.
The third condition is scale: the system serves more than 100,000 users or processes more than 1,000 identity resolution requests per second. Below these thresholds, a well-designed monolith with proper caching will outperform a modular system in both latency and operational simplicity. The fourth condition is regulatory pressure: if you operate in a jurisdiction that requires strict data segregation (e.g., GDPR, HIPAA), modular identity can help enforce boundaries. But if you are not under such requirements, the added audit complexity may not be worth it.
There are also situations where modular identity actively hurts. If your organization has a low tolerance for latency (e.g., real-time trading systems), the extra network hops of lazy claim resolution are unacceptable. If your security team requires that all identity data be stored in a single encrypted store, modularity violates that constraint. If your team is already struggling with operational stability (frequent outages, poor monitoring), adding modular identity will compound the problem.
Alternatives to Consider
Before adopting modular identity, consider two simpler alternatives. The first is claims filtering at the gateway: a single identity store that returns all claims, but the API gateway strips claims that the downstream service is not authorized to see. This gives you data isolation without modular storage. The downside is that the schema is still monolithic, so schema changes still require coordination. The second alternative is federated identity with scoped tokens: use OAuth scopes to limit which claims are included in each token. This works well when the number of claim sets is small (fewer than five) and the claims are not independently versioned.
Open Questions and FAQ
How do you handle cross-module transactions?
Cross-module transactions (e.g., update user email in both the authentication module and the profile module) are notoriously difficult. The safest approach is to avoid them: designate one module as the source of truth for each claim and propagate changes via asynchronous events. If you need atomicity, consider a saga pattern with compensating actions, but this adds significant complexity. In practice, most teams accept eventual consistency for identity data, as long as the window of inconsistency is bounded (e.g., under one second).
What happens when a module goes down?
Each module should have a circuit breaker. If a module is unavailable, the identity resolution should return the claims it has and mark the missing module's claims as 'stale' or 'unavailable.' The consuming service can then decide whether to proceed with partial data or fail. This requires that every consumer handle missing claims gracefully—a design constraint that is often overlooked. A fallback strategy is to cache the last known values from each module and serve those when the module is down.
How do you version the identity bus itself?
The bus protocol (the contract between the gateway and modules) should be versioned independently of the claim schemas. Start with a simple version header in the module registration and the claim request. When you need to change the bus protocol (e.g., adding a new metadata field), you can run both versions side by side. In practice, the bus protocol changes rarely—once or twice a year—so versioning is straightforward.
Is modular identity compatible with existing OIDC providers?
Yes, and this is the most common deployment pattern. The OIDC provider issues the core ID token and access token. The modular identity layer sits behind the provider: when a service receives an access token, it calls the claim gateway to resolve additional modules. The gateway uses the access token to authenticate the request and then fetches claims from the relevant modules. This keeps the OIDC provider simple and allows the modular layer to evolve independently.
What is the smallest team that should attempt this?
Based on the patterns we've seen, a team of at least five engineers dedicated to identity infrastructure is the minimum. Smaller teams struggle with the operational overhead. If you have fewer than five engineers, start with a simpler approach (claims filtering or scoped tokens) and migrate to modular identity only when the team grows or the complexity demands it.
Summary and Next Experiments
Modular identity architecture is a protocol for decomposing the user's identity into independently evolvable claim modules, connected by a gateway and governed by versioned schemas. It is not a default choice—it is a response to specific pressures: multiple teams, high change velocity, scale, or regulatory requirements. When applied correctly, it reduces coordination costs, limits blast radius, and enables faster releases. When applied incorrectly, it adds latency, complexity, and maintenance burden without proportional benefit.
If you are considering this approach, start with a small experiment. Pick one claim set that changes frequently and is owned by a single team. Extract it into a module behind a gateway. Measure the impact on release frequency, latency, and team satisfaction. Run the experiment for two sprints. If the results are positive, expand to a second module. If not, revert and reconsider the alternatives.
Three specific next moves: (1) audit your current identity schema for claims that change at different rates—these are candidates for modularization. (2) Implement a claim gateway with a single module and measure the overhead. (3) Set up telemetry to track module usage and latency before you need it. The goal is not to modularize everything, but to find the right boundaries that make your identity system a platform for velocity, not a bottleneck.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!