| Users | Roles | Permissions | Access Checks per Second | System Changes |
|---|---|---|---|---|
| 100 | 10 | 50 | 200 | Simple centralized auth service; direct DB queries for access checks |
| 10,000 | 100 | 500 | 20,000 | Introduce caching for permissions; use token-based auth (JWT); microservices query cache |
| 1,000,000 | 1,000 | 5,000 | 2,000,000 | Distributed cache (e.g., Redis); auth service scaled horizontally; async permission updates; token introspection service |
| 100,000,000 | 10,000 | 50,000 | 200,000,000 | Sharded permission storage; global CDN for token validation; edge caching; fine-grained permission microservices; event-driven updates |
Role-based access control in Microservices - Scalability & System Analysis
The first bottleneck is the authorization service database that stores roles and permissions. As user count and access checks grow, frequent permission lookups cause high read load and latency. Direct DB queries for each access check become too slow and resource-heavy.
- Caching: Use in-memory caches (e.g., Redis) to store user roles and permissions for fast access.
- Token-based Auth: Use JWT tokens embedding roles/permissions to reduce calls to auth service.
- Horizontal Scaling: Run multiple instances of the auth service behind a load balancer.
- Sharding: Partition role and permission data by user groups or regions to distribute load.
- Event-driven Updates: Use message queues to update caches asynchronously when roles or permissions change.
- Edge Caching and CDN: For global scale, cache tokens and permission data closer to users.
- At 1M users with 2M access checks/sec, assuming 1KB per permission cache entry, Redis needs ~2GB RAM for hot data.
- Network bandwidth for 2M requests/sec with 1KB payload = ~2GB/s (~16Gbps), requiring high network capacity.
- Auth service instances: each handles ~5,000 QPS, so ~400 instances needed at peak.
- Storage for roles/permissions: tens of GBs, depending on complexity and history retention.
Start by explaining the RBAC components: users, roles, permissions, and access checks. Then discuss how load grows with users and requests. Identify the database as the first bottleneck. Propose caching and token-based auth to reduce load. Finally, mention horizontal scaling and sharding for very large scale. Keep answers structured and focused on bottlenecks and solutions.
Your database handles 1000 QPS. Traffic grows 10x to 10,000 QPS. What do you do first?
Answer: Introduce caching for roles and permissions to reduce direct database queries. This lowers DB load and improves response time before scaling DB or services.
Practice
Solution
Step 1: Understand RBAC concept
RBAC assigns permissions to users based on their roles, simplifying access management.Step 2: Identify RBAC purpose in microservices
In microservices, RBAC controls who can access which service or API based on roles.Final Answer:
To assign permissions to users based on their roles -> Option CQuick Check:
RBAC = Role-based permission assignment [OK]
- Confusing RBAC with encryption
- Thinking RBAC monitors network traffic
- Assuming RBAC automates deployment
Solution
Step 1: Identify correct role structure
A role should have a name and a list of permissions it grants.Step 2: Match structure to options
{"role": "admin", "permissions": ["read", "write"]}correctly shows a role with permissions as a list, matching RBAC design.Final Answer:
{"role": "admin", "permissions": ["read", "write"]} -> Option BQuick Check:
Role = name + permissions list [OK]
- Confusing user with role
- Using 'permission' as role name
- Assigning access level instead of permissions
def can_access(user_role, action):
permissions = {
"user": ["read"],
"admin": ["read", "write", "delete"]
}
return action in permissions.get(user_role, [])
print(can_access("user", "delete"))
What is the output?Solution
Step 1: Understand permissions dictionary
The "user" role has only ["read"] permission, no "delete".Step 2: Check if "delete" is in user permissions
Since "delete" is not in ["read"], the function returns False.Final Answer:
False -> Option DQuick Check:
"delete" in user permissions = False [OK]
- Assuming all actions allowed for user
- Expecting KeyError for missing keys
- Confusing True/False return values
def check_access(role, permission):
role_permissions = {
"editor": ["read", "write"],
"viewer": ["read"]
}
return permission in role_permissions[role]
print(check_access("admin", "write"))
What is the problem and how to fix it?Solution
Step 1: Identify error cause
Accessing role_permissions["admin"] causes KeyError because "admin" key is missing.Step 2: Fix by safe dictionary access
Use role_permissions.get(role, []) to return empty list if role missing, avoiding error.Final Answer:
KeyError occurs; fix by using role_permissions.get(role, []) -> Option AQuick Check:
Missing key causes KeyError; get() avoids it [OK]
- Adding roles without permissions
- Confusing syntax errors with runtime errors
- Ignoring missing key errors
Solution
Step 1: Consider scalability and security needs
Enforcing RBAC centrally avoids duplication and reduces risk of inconsistent checks.Step 2: Identify best enforcement point
API Gateway is the central entry point, ideal for RBAC enforcement before microservices.Final Answer:
At the API Gateway before requests reach microservices -> Option AQuick Check:
Central RBAC at API Gateway = scalable & secure [OK]
- Enforcing RBAC only in microservices causes duplication
- Relying on client-side enforcement is insecure
- Using database permissions alone misses API-level control
Ready to prove it?
Pass the test and this pattern moves unknown
