← Figma Interview Insights

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

SeniorPrefer not to say
Jun 2026

Summary

Figma system design round focused entirely on building a document editing layer with undo/redo and batching. Pretty deep dive, more like a whiteboard session than a typical design interview.

Questions Asked (6)

Q1

Design a document layer with apply(op), undo(), and redo() operations. How do you structure the underlying data to support this?

System DesignAlgorithms & Data StructuresTechnical Trade-offs
Author's notes

I went straight to two stacks, undo and redo, which is the obvious answer.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements: what operations are needed, what types of changes (e.g., property updates, structural changes), and whether collaboration is required. Then propose a command pattern where each operation is an object with apply and inverse methods, stored in an undo stack and a redo stack. Discuss how to handle memory, batching, and potential optimizations like persistent data structures.

Pro tip: Mention that in a collaborative editor like Figma, you need to handle concurrent operations and that undo/redo must be scoped per user, which often requires operational transformation or CRDTs. This shows you understand the real-world complexity beyond a simple stack.

1. Clarify requirements and constraints

Ask about the types of operations, expected frequency, memory constraints, and whether collaboration or persistence is needed. This ensures your design fits the context.

2. Choose a command-based architecture

Represent each operation as a command object with apply and inverse methods. This encapsulates the logic and makes undo/redo straightforward.

3. Design the undo/redo stacks

Use two stacks: one for undo (past operations) and one for redo (undone operations). On apply, push to undo stack and clear redo stack; on undo, pop from undo, apply inverse, push to redo; on redo, pop from redo, apply operation, push to undo.

4. Address memory and performance

Discuss batching operations, using persistent data structures to share state, and limiting history size. Consider lazy inverse computation or storing deltas instead of full snapshots.

5. Handle edge cases and collaboration

Mention how to deal with concurrent edits (e.g., operational transformation or CRDTs), and how to scope undo/redo per user in a multiplayer setting.

Key Points to Mention

  • Command pattern with apply and inverse methods for each operation
  • Two stacks: undo stack and redo stack, with clear rules for pushing and popping
  • Memory management: batching, persistent data structures, or limiting history
  • Handling structural changes (e.g., adding/removing nodes) vs property changes
  • Collaboration considerations: operational transformation or CRDTs for concurrent undo/redo
  • Trade-offs between simplicity and scalability, and how to test the design

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

Q2

Add batching support with beginBatch(), apply(op), and commitBatch(). The entire batch should undo as a single step. How do you implement this?

System DesignAlgorithms & Data Structures
Author's notes

Felt more comfortable here.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, then design a batching mechanism that groups operations and records a single undo entry. Explain how you would implement beginBatch, apply, and commitBatch, ensuring atomicity and efficient undo.

Pro tip: Emphasize that the batch should be treated as a single transaction: if any operation fails, the entire batch should be rolled back, and the undo stack should only contain the batch as one entry.

1. Clarify Requirements

Ask about expected batch size, error handling, and whether nested batches are needed. Confirm that undo should revert the entire batch in one step.

2. Design Data Structures

Propose a Batch object that stores a list of operations and a composite undo function. The undo stack will hold either individual operations or batches.

3. Implement Batching Methods

beginBatch initializes a new batch and sets a flag to route apply calls into it. apply adds the operation to the batch and executes it. commitBatch finalizes the batch, pushes it onto the undo stack, and clears the batching state.

4. Handle Undo and Error Cases

Ensure that undoing a batch reverses all operations in reverse order. If an error occurs during apply, abort the batch and undo any already-applied operations.

5. Discuss Optimizations and Edge Cases

Mention potential optimizations like merging operations or lazy execution, and address edge cases such as empty batches or nested batches.

Key Points to Mention

  • Atomicity: the batch must be all-or-nothing for undo.
  • Composite pattern: treat a batch as a single undoable unit.
  • State management: track whether a batch is active and route operations accordingly.
  • Error handling: rollback on failure to maintain consistency.
  • Undo stack integration: push the batch as one entry, not individual operations.
  • Performance: consider memory and time overhead of storing operations.

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

Q3

How would you optimize batch undo for both time and space? Consider compressing consecutive operations and storing inverse operations efficiently.

Technical Trade-offsAlgorithms & Data StructuresSystem Design
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 of the undo system, then propose a design that uses operation compression and inverse operations to optimize both time and space. Discuss trade-offs between different compression strategies and how they affect undo/redo performance, and consider edge cases like memory limits and concurrency.

Pro tip: Emphasize that undo/redo is a core user experience feature, so optimizations must not compromise correctness or responsiveness; mention that you would instrument the system to measure actual memory and latency improvements before and after optimization.

1. Clarify Requirements and Constraints

Ask about the expected scale (number of operations, memory limits), latency requirements, and whether undo/redo must be persistent across sessions. This ensures your optimization targets the right bottlenecks.

2. Design Operation Compression

Propose compressing consecutive operations of the same type (e.g., multiple character insertions into a single string insert) or using delta encoding. Discuss how to detect compressible sequences and the trade-off between compression ratio and decompression overhead.

3. Efficient Inverse Operation Storage

Store inverse operations compactly, e.g., by storing only the minimal data needed to revert (like the previous state or a diff). Consider using a command pattern with reversible operations and sharing data between forward and inverse operations.

4. Analyze Time and Space Trade-offs

Compare approaches: eager vs lazy compression, in-memory vs on-disk storage, and the impact on undo/redo speed. Quantify space savings and time costs, and propose a hybrid approach if needed.

5. Address Edge Cases and Scalability

Discuss handling of non-compressible operations, memory pressure (e.g., evicting old history), and concurrency (e.g., collaborative editing). Mention how to test and monitor the system.

Key Points to Mention

  • Operation compression techniques: run-length encoding, delta encoding, and merging consecutive operations.
  • Inverse operation representation: storing minimal state or diffs to reduce memory footprint.
  • Time-space trade-offs: compression reduces space but may increase undo time due to decompression.
  • Data structures: use of stacks, linked lists, or persistent data structures for efficient undo/redo.
  • Memory management: setting history limits, using weak references, or spilling to disk.
  • Correctness and user experience: ensuring undo/redo remains fast and reliable under optimization.

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

Q4

What happens to the redo stack after an undo, and what happens to it after new edits are applied following an undo?

System DesignTechnical Trade-offs
Author's notes

Classic redo semantics question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Explain the standard undo/redo model: undo moves the last action from the undo stack to the redo stack, and any new edit after an undo clears the redo stack. Then connect this to real-world design tools like Figma, emphasizing why clearing the redo stack is necessary to avoid branching history and maintain a linear timeline.

Pro tip: Mention that some applications offer a 'redo history' that persists after new edits, but this is non-standard and can confuse users; Figma likely follows the standard model for predictability. Also, note that the redo stack is typically cleared to prevent inconsistent states and to simplify the mental model for users.

1. Define the stacks

Briefly describe the undo and redo stacks as LIFO structures that store actions or states. Clarify that undo stack holds actions that can be undone, and redo stack holds actions that can be redone.

2. Explain undo behavior

State that when an undo is performed, the most recent action is popped from the undo stack, reversed, and pushed onto the redo stack. This allows the action to be redone later.

3. Explain new edit after undo

Describe that when a new edit is applied after an undo, the redo stack is cleared (or becomes invalid) because the new action creates a new branch in history. This prevents redoing actions that are no longer in the current timeline.

4. Discuss implications and trade-offs

Mention why clearing the redo stack is standard: it avoids ambiguity, maintains a linear history, and aligns with user expectations. Optionally, contrast with alternative models (e.g., persistent redo) and their pros/cons.

5. Relate to Figma's context

Connect to Figma's collaborative design tool: emphasize that predictable undo/redo is crucial for user experience, and that clearing redo prevents conflicts in a multi-user environment (though Figma's real-time collaboration may have more complex handling).

Key Points to Mention

  • Undo stack and redo stack as LIFO data structures
  • Undo operation: pop from undo stack, push onto redo stack
  • New edit after undo: clear redo stack to avoid branching history
  • Linear history model vs. branching (e.g., Git-like) models
  • User expectations and predictability in design tools
  • Potential edge cases: multiple undos, redo after multiple undos, and collaborative editing

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

Q5

How do you handle partial failures within a batch? If one operation in a batch fails mid-way, what should happen?

System DesignTechnical Trade-offsAdaptability & Ambiguity
Author's notes

I blanked for a second here.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements and constraints, such as whether the batch must be atomic or if partial success is acceptable. Then discuss trade-offs between different failure handling strategies, and propose a solution that aligns with the system's needs, emphasizing idempotency, retries, and observability.

Pro tip: Demonstrate maturity by acknowledging that the 'right' answer depends on business requirements and system constraints, and that you would collaborate with stakeholders to define the desired behavior. Also, mention that you'd design for idempotency and use dead-letter queues to handle persistent failures.

1. Clarify Requirements

Ask questions to understand the batch's purpose, whether partial success is acceptable, and the impact of failures on downstream systems. Determine if the batch must be atomic or if it can be processed in a best-effort manner.

2. Evaluate Trade-offs

Discuss the pros and cons of different approaches: all-or-nothing (atomic) vs. partial success with error handling. Consider factors like data consistency, user experience, and system complexity.

3. Design for Idempotency and Retries

Explain how you would make operations idempotent to allow safe retries, and implement retry mechanisms with exponential backoff for transient failures. Mention the use of unique identifiers to detect and skip already-processed items.

4. Handle Persistent Failures

Describe how to isolate and handle items that repeatedly fail, such as using a dead-letter queue for manual inspection or automated alerts. Ensure that failures are logged with sufficient context for debugging.

5. Monitor and Recover

Outline monitoring and alerting for batch processing, and discuss recovery strategies like reprocessing failed items or compensating transactions. Emphasize the importance of observability and clear error reporting.

Key Points to Mention

  • Atomicity vs. partial success: discuss when each is appropriate and the implications for data consistency.
  • Idempotency: ensure operations can be safely retried without duplicating side effects.
  • Retry strategies: exponential backoff, jitter, and circuit breakers for transient failures.
  • Dead-letter queues: isolate and handle persistent failures for later analysis or manual intervention.
  • Observability: logging, metrics, and tracing to monitor batch progress and diagnose failures.
  • Compensating transactions: for rolling back or correcting partial successes in distributed systems.

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

Q6

What are the edge cases for this system? Think about empty stacks, nested batches, and overlapping batch calls.

System DesignAlgorithms & Data Structures
Author's notes

Empty stacks are trivial, just no-ops.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Systematically enumerate edge cases by categorizing them into input, state, and interaction scenarios. For each category, consider empty, single, multiple, and nested cases, and how they affect the system's behavior. Prioritize edge cases based on likelihood and impact, and suggest how to handle them in design or testing.

Pro tip: Demonstrate that you think about edge cases not just as bugs but as opportunities to improve system robustness and user experience. Mention how you would document and test these edge cases to ensure they are handled correctly.

1. Identify system components and operations

Clarify what the system does, focusing on stacks, batches, and batch calls. Understand the expected normal flow to contrast with edge cases.

2. Enumerate edge cases by category

Break down edge cases into input (empty, single, multiple), state (empty stack, full stack), and interaction (nested batches, overlapping calls).

3. Analyze impact and likelihood

For each edge case, assess how it could break the system or cause incorrect behavior, and how likely it is to occur in practice.

4. Propose handling strategies

Suggest design or implementation approaches to handle each edge case, such as validation, error handling, or fallback mechanisms.

5. Summarize and prioritize

Conclude with a prioritized list of edge cases to address, and mention how you would test them.

Key Points to Mention

  • Empty stack: operations like pop or peek on an empty stack should be handled gracefully (e.g., return null or throw a specific error).
  • Nested batches: ensure that batch operations can be nested without causing stack overflow or incorrect ordering; consider recursion depth and state management.
  • Overlapping batch calls: handle concurrent or overlapping batch calls to avoid race conditions, data corruption, or inconsistent state.
  • Single-element stack: edge case where stack has exactly one element; operations should work without off-by-one errors.
  • Batch size limits: consider maximum batch size and how to handle batches that exceed limits (e.g., chunking or rejection).
  • Error propagation: in nested or overlapping batches, ensure errors are propagated correctly and don't leave the system in an inconsistent state.

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