Uber | SDE-2 – Frontend Engineer | Interview Experience
Summary
This post details my interview experience for an SDE-2 Frontend Engineer role at Uber, which involved three rounds. The rounds focused on implementing a memoize utility, an async scheduler with concurrency limits, and a task runner with dependencies.
Full Experience
🧠 Round 1 (Screening): Memoization + Data Structures Problem: Implement a memoize() utility with nested argument support using a trie-like structure.
Given a function, memoize it such that multiple arguments (primitives + refs) are cached correctly.
Required building a trie inside a Map to support nested argument caching.
Discussed time-space tradeoffs, argument uniqueness, and cache invalidation strategies.
⚙️ Round 2: Async Execution with Limit Problem: Implement a scheduler that runs async tasks with a concurrency limit (like Promise.all with limit = 2).
I used a queue + counter mechanism to throttle concurrent executions.
Discussion included edge cases (failures, infinite queues) and performance under load.
Covered task queue backpressure and the role of microtasks vs macrotasks.
🧩 Round 3: Task Runner with Dependencies Problem: Execute a set of async tasks with dependencies (like a build graph).
Input: tasks A–E with dependencies { D: ['A','B'], E: ['C','D'] }
Wrote a runTasks utility to resolve and run in order using a custom dependency resolver (not topo sort).
My approach worked but the interviewer hinted I should’ve used topological sorting.
⚠️ Feedback: Functional but the interviewer seemed unsatisfied without topo sort.
Interview Questions (3)
Given a function, memoize it such that multiple arguments (primitives + refs) are cached correctly. Required building a trie inside a Map to support nested argument caching.
Implement a scheduler that runs async tasks with a concurrency limit (like Promise.all with limit = 2).
Execute a set of async tasks with dependencies (like a build graph). Input: tasks A–E with dependencies { D: ['A','B'], E: ['C','D'] }.