← Stripe Interview Insights

Stripe·Software Engineer·Onsite - System Design / Architecture·Senior

SeniorPrefer not to say
May 2026

Summary

Stripe system design round for a software engineer role, pretty deep on access control. They wanted both a working implementation and a real discussion about complexity tradeoffs, which I wasn't fully expecting going in.

Questions Asked (4)

Q1

Design and implement a role-based access control system that supports creating users, roles, and permissions; assigning permissions to roles; assigning one or more roles to users; and checking whether a user has a given permission.

System DesignAlgorithms & Data StructuresData Modeling
Author's notes

I started with the obvious stuff, hashmaps keyed by user id pointing to sets of role ids, roles pointing to sets of permission strings.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and scale, then design a normalized data model with users, roles, permissions, and junction tables. Discuss efficient permission checks using caching or precomputed sets, and outline the core APIs for managing entities and assignments.

Pro tip: At Stripe, emphasize security and auditability: mention how you would log permission changes and ensure least privilege. Also, consider using an inverted index for fast permission checks.

1. Clarify Requirements and Scale

Ask about expected number of users, roles, permissions, and query patterns. Determine if permissions are hierarchical or flat, and if real-time updates are needed.

2. Design Data Model

Propose tables: users, roles, permissions, user_roles (many-to-many), role_permissions (many-to-many). Include indexes on foreign keys for efficient lookups.

3. Define Core Operations and APIs

Outline CRUD operations for users, roles, permissions, and assignment endpoints. Specify how to check permissions (e.g., GET /users/{id}/permissions/{permission}).

4. Optimize Permission Checks

Discuss caching strategies (e.g., Redis) or precomputing user-permission mappings. Consider using bitmasks or sets for fast membership tests.

5. Address Security and Scalability

Mention audit logging, role hierarchy, and handling high read throughput. Discuss sharding or replication if needed.

Key Points to Mention

  • Normalized schema with junction tables for many-to-many relationships
  • Efficient permission check using caching or precomputed sets
  • Role hierarchy and inheritance for complex scenarios
  • Audit logging for security and compliance
  • API design for managing entities and assignments
  • Scalability considerations: indexing, sharding, and read replicas

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Extend the system to support role hierarchy, where a role can inherit permissions from a parent role.

System DesignTechnical Trade-offsAlgorithms & Data Structures
Author's notes

This is where it got interesting.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, such as the depth of hierarchy, frequency of permission checks, and whether roles can have multiple parents. Then propose a data model (e.g., directed acyclic graph) and an algorithm to resolve permissions efficiently, discussing trade-offs between precomputation and on-the-fly resolution. Finally, address edge cases like cycles, caching, and consistency.

Pro tip: Mention that you would enforce acyclic constraints at write time and consider caching resolved permissions with invalidation on hierarchy changes, showing awareness of production concerns.

1. Clarify Requirements

Ask about hierarchy depth, multiple inheritance, performance needs, and consistency requirements to scope the solution.

2. Design Data Model

Represent roles as nodes in a directed acyclic graph (DAG) with parent-child relationships, ensuring no cycles.

3. Choose Permission Resolution Strategy

Decide between precomputing effective permissions (e.g., via topological sort) or resolving on-demand with caching, weighing trade-offs.

4. Handle Edge Cases and Scalability

Address cycle detection, cache invalidation, and efficient lookups for deep hierarchies or high query volume.

5. Discuss Trade-offs and Alternatives

Compare approaches like materialized paths, closure tables, or graph databases, and justify your choice based on requirements.

Key Points to Mention

  • Directed acyclic graph (DAG) representation to prevent cycles
  • Topological sorting for precomputing effective permissions
  • Caching strategies and invalidation on hierarchy changes
  • Handling multiple inheritance and conflict resolution
  • Performance considerations for deep hierarchies and frequent checks
  • Consistency and atomicity when updating role hierarchy

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

Further extend the system to support resource-scoped permissions, for example a permission like 'edit' that applies only to a specific resource id.

System DesignData ModelingTechnical Trade-offs
Author's notes

Honestly the trickiest part of the whole question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: what types of resources, how permissions are assigned, and the expected scale. Then propose a data model that captures resource-scoped permissions, such as a permission table with a resource_id column or a separate resource_permissions table. Discuss trade-offs between flexibility, performance, and complexity, and outline how to enforce these permissions in the authorization layer.

Pro tip: Mention that resource-scoped permissions can be modeled as a tuple (subject, action, resource) and that this aligns with common authorization frameworks like RBAC with resource qualifiers or ABAC. Also, consider how to handle wildcard or hierarchical resources (e.g., 'edit' on all resources of a type) to show foresight.

1. Clarify Requirements

Ask questions to understand the scope: what resources need scoping, how permissions are granted (per user, per role), and the expected query patterns (e.g., checking if a user can edit a specific resource).

2. Propose Data Model

Suggest extending the existing permission model with a resource identifier. For example, add a resource_id column to the permissions table, or create a new table linking permissions to resources. Discuss normalization vs. denormalization.

3. Address Enforcement

Explain how the authorization check would work: given a user, action, and resource, query the permission store to see if a matching permission exists. Consider caching strategies for performance.

4. Discuss Trade-offs

Compare approaches: a single table with nullable resource_id vs. separate tables for global and scoped permissions. Consider impact on query complexity, indexing, and migration.

5. Handle Edge Cases

Mention how to support wildcards (e.g., 'edit' on all resources of a type), hierarchical resources (e.g., parent-child), and bulk operations. Also discuss auditing and revocation.

Key Points to Mention

  • Data model: adding resource_id to permissions table or creating a resource_permissions join table.
  • Authorization check: querying for (user, action, resource) tuple, possibly with caching.
  • Trade-offs: flexibility vs. performance, complexity of queries, and indexing strategies.
  • Scalability: how the model handles many resources and permissions, and potential need for sharding or partitioning.
  • Integration with existing RBAC: how resource-scoped permissions fit with roles and global permissions.
  • Edge cases: wildcard permissions, hierarchical resources, and permission inheritance.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Walk through your data structure choices and explain how you keep permission checks O(1) amortized across all the extensions.

Algorithms & Data StructuresTechnical Trade-offsSystem Design
Author's notes

They saved this as a wrap-up discussion and it felt like a mini oral exam.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by framing the problem: you need to support permission checks across multiple extensions with O(1) amortized time. Then walk through your data structure choices (e.g., hash maps, bitsets, or tries) and explain how they enable constant-time lookups, including how you handle dynamic updates and amortization.

Pro tip: Emphasize that amortized O(1) often comes from careful design of update operations (like rehashing or path compression) and that you measure worst-case latency, not just average, to ensure consistent performance.

1. Clarify requirements and constraints

Restate the problem: permission checks must be O(1) amortized across all extensions, implying frequent reads and occasional writes. Ask about scale, update frequency, and consistency requirements.

2. Choose core data structures

Select structures like hash maps for direct key lookups, bitsets for compact permission flags, or tries for hierarchical permissions. Explain why each fits the access pattern.

3. Design for O(1) amortized checks

Describe how lookups achieve constant time: e.g., precomputed permission sets, caching, or union-find with path compression. Discuss how updates (e.g., adding an extension) are handled to maintain amortized bounds.

4. Address extensions and scalability

Explain how the design extends to new extensions without degrading performance, such as using consistent hashing or sharding. Mention any trade-offs (memory vs. speed).

5. Validate with complexity analysis and edge cases

Provide amortized analysis (e.g., using potential method) and discuss edge cases like concurrent updates or permission revocation. Suggest monitoring and fallback strategies.

Key Points to Mention

  • Hash maps for O(1) average-case lookups, with collision handling (e.g., chaining or open addressing) and resizing strategies.
  • Bitsets for compact storage and fast bitwise operations when permissions are boolean flags.
  • Amortized analysis techniques (e.g., accounting method, potential method) to justify O(1) amortized time.
  • Caching or memoization of permission checks for hot paths, with invalidation on updates.
  • Trade-offs between memory usage and speed, and how to handle worst-case scenarios (e.g., hash collisions).
  • Concurrency considerations: read-write locks, copy-on-write, or lock-free data structures for high throughput.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.