Series: Centralized User Management (Part 1: Architecture & Database)
This is the first part of my series: Mastering Centralized User Management. Here is what we will cover:
Part 1: The Architecture & Database Design (Current)
Part 2: Building the Next.js API Hub
Part 3: Connecting Laravel to the Hub
Part 4: Syncing & Advanced Features
1. Introduction: The Operational Risk of Fragmented Identity
In the lifecycle of a growing enterprise ecosystem, there is a recurring point of failure that often goes unaddressed until it becomes a critical liability: fragmented identity management. When an organization operates multiple independent applications — such as a suite of legacy Laravel services — the default path is often to allow each service to manage its own user table, authentication logic, and authorization rules.
This approach introduces significant operational risks. From a security perspective, it creates “access drift,” where a user terminated in one system retains active sessions in three others. From a governance standpoint, it results in duplicated user records, inconsistent role assignments across platforms, and an audit trail that is impossible to reconstruct without manual, error-prone data consolidation.
To achieve long-term maintainability and security, engineers must shift from managing users manually at the service level to establishing a centralized Single Source of Truth (SSoT).
2. Defining the Core Problem: Architectural Anti-Patterns
Fragmented user management is not merely a localized inconvenience; it is a fundamental architectural anti-pattern. Several specific issues arise when identity is decentralized:
Duplicated Logic and Records
When Service A and Service B both maintain a users table, the system inevitably drifts. Email updates, password resets, and profile changes must be synchronized via fragile webhooks or, worse, manual intervention. This redundancy increases storage costs and, more importantly, cognitive load for developers who must maintain multiple authentication middlewares.
Authorization Governance Failures
Authorization is frequently conflated with authentication. When role-based access control (RBAC) is hardcoded into individual service repositories, updating a global permission (e.g., “Editor” can now access “Analytics”) requires a coordinated deployment across every service in the stack. This lack of centralized governance makes it nearly impossible to enforce consistent security policies.
Audit Exposure and Compliance Risks
Under regulations such as GDPR or SOC2, the ability to provide a comprehensive audit log of user access is mandatory. In a fragmented system, there is no unified log of when a user logged in, which services they accessed, or who granted them elevated privileges. This creates a massive liability during compliance audits.
3. Designing a Centralized Architecture
To mitigate these risks, we propose a “Hub and Spoke” architecture. In this model, a centralized Identity Hub handles all identity concerns, while individual applications (the spokes) delegate authentication and authorization to this central authority.
The Identity Boundary
The Hub defines the boundary for all Identity and Access Management (IAM). No spoke application should ever write directly to the user database. Instead, spokes interact with the Hub via secure API contracts.
Structural Components
- Authentication Layer: Centralizes credential verification, session management, and JWT issuance.
- Authorization Layer: A unified RBAC/ABAC engine that defines what a user can do across the entire ecosystem.
- The API Hub: Built with Next.js, serving as the gateway for both administrative identity management and external service verification requests.
Arsitektur Program (https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ci1ivgnaionh6dst1lan.png)
By decoupling identity, we ensure that the Laravel “spokes” remain thin and focused on their specific business domains, while the Next.js “hub” handles the heavy lifting of security and governance.
4. Why Next.js as the Core Hub?
The selection of Next.js as the engine for a centralized Identity Hub is a strategic architectural choice. While traditional IAM solutions like Keycloak or Auth0 exist, building a custom Hub on Next.js provides the perfect balance between a modular monolith and microservices.
Full-Stack Synergy
Next.js provides a unified environment for building both the administrative UI (for managing users and permissions) and the high-performance API Route Handlers required for service-to-service communication. This reduces the deployment footprint and simplifies the development lifecycle.
Serverless and Edge Readiness
Modern identity hubs must be highly available. Next.js’s ability to run on edge runtimes or serverless functions allows the authentication layer to be geographically distributed, reducing latency for global service requests.
Developer Velocity vs. Governance
Compared to a pure microservices approach, using Next.js allows us to maintain the identity logic in a single, well-tested repository while providing the necessary interfaces (APIs) for other services to consume. It acts as a “Governance Layer” that can be scaled independently of the consuming applications.
5. Database Design Strategy: Normalization and Scale
A centralized system is only as strong as its underlying data model. We require a relational schema that supports fine-grained access control while remaining performant under high read loads.
Normalized Relational Schema
We will utilize PostgreSQL for its strict schema enforcement and advanced indexing capabilities. The schema focuses on a robust RBAC model.
Entity Breakdown:
- users: Core identity data (UUIDs, hashed credentials, MFA status).
- roles: High-level groupings (e.g., Admin, Manager, Auditor).
- permissions: Atomic actions (e.g., inventory.write, finance.view).
- role_permissions: The mapping layer defining the capabilities of each role.
- user_roles: Mapping users to one or more roles.
// schema.prisma
model User {
id String @id @default(uuid())
email String @unique
passwordHash String
fullName String?
isActive Boolean @default(true)
roles UserRole[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email])
}
model Role {
id String @id @default(uuid())
name String @unique
description String?
permissions RolePermission[]
users UserRole[]
}
model Permission {
id String @id @default(uuid())
slug String @unique // e.g., 'users.create'
description String?
roles RolePermission[]
}
model RolePermission {
roleId String
permissionId String
role Role @relation(fields: [roleId], references: [id])
permission Permission @relation(fields: [permissionId], references: [id])
@@id([roleId, permissionId])
}
model UserRole {
userId String
roleId String
user User @relation(fields: [userId], references: [id])
role Role @relation(fields: [roleId], references: [id])
@@id([userId, roleId])
}
Performance and Indexing
Since authentication is a read-heavy operation, we prioritize B-tree indexes on the email and slug columns. For authorization checks—which often involve joining multiple tables—we will implement caching strategies (such as Redis) in Part 2 to prevent database bottlenecks during peak traffic.
Audit Logging Considerations
Every change to the user_roles or role_permissions tables must be captured. In an enterprise environment, "who granted this access" is as important as "who has this access." We implement this via an audit_logs table that captures the actor, the action, and the timestamp for every administrative change.
6. Governance and Scalability Considerations
Horizontal Scaling
The Next.js Hub is stateless by design. Sessions are managed via signed JWTs or short-lived tokens, allowing us to spin up multiple instances of the Hub behind a load balancer without worrying about session affinity.
Migration Strategy
Moving from legacy scattered systems to a Centralized Hub requires a “Parallel Run” strategy:
- Shadow Write: Keep writing to legacy DBs while simultaneously populating the Centralized Hub.
- Lazy Migration: Migrate users to the Hub the next time they log in.
- Deprecation: Once the Hub reaches 100% data parity, flip the switch and point the Laravel spokes to the Hub’s API.
Risk Mitigation
The SSoT becomes a Single Point of Failure. To mitigate this, we implement:
- Database Replication: Multi-region PostgreSQL deployments.
- Rate Limiting: Protecting the Hub from brute-force attacks or malfunctioning spoke services.
- Circuit Breakers: Ensuring that if the Hub is down, spoke services can fail gracefully (e.g., via cached permissions).
7. Conclusion
Establishing a Single Source of Truth for user management is not just a technical upgrade; it is a foundational move toward architectural maturity. By centralizing identity in a Next.js and PostgreSQL Hub, we eliminate data redundancy, enforce strict security governance, and create a scalable framework that can support any number of integrated services.
In this first part, we have laid the theoretical and structural groundwork. However, an architecture is only as good as its implementation.
In Part 2: Building the Next.js API Hub, we will move into the implementation phase, focusing on creating secure API Route Handlers, implementing JWT-based authentication, and building the logic that will allow our external Laravel applications to communicate with our new Source of Truth.
Top comments (0)