← Ramp Interview Insights

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

SeniorPrefer not to say
Jun 2026

Summary

Interviewed at Ramp for a software engineering role and got a system design question that was less about architecture diagrams and more about writing real client logic against a live API. Interesting format, not what I expected.

Questions Asked (4)

Q1

You're given an API that returns the next location to visit in a maze. Starting from some initial position, design the client logic to repeatedly call the API until you reach the destination, including termination conditions, error handling, and tests.

API & IntegrationsSystem DesignTechnical Trade-offs
Author's notes

This one took me a minute to parse.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the API contract, including request/response formats, error codes, and rate limits. Then design a loop that calls the API, handles errors with retries and backoff, and terminates when the destination is reached or a maximum number of steps is exceeded. Finally, outline tests for normal flow, edge cases, and failure scenarios.

Pro tip: Mention idempotency and state management: if the API is not idempotent, you may need to track visited locations to avoid infinite loops. Also, discuss how you would handle API changes or versioning.

1. Clarify requirements and API contract

Ask about the API's request/response schema, error codes, rate limits, and whether it's idempotent. Confirm the definition of 'destination' and how it's signaled.

2. Design the core loop

Outline a loop that calls the API with the current position, updates the position based on the response, and checks for termination conditions (destination reached, max steps, or error).

3. Implement error handling and resilience

Add retries with exponential backoff for transient errors, handle non-retryable errors by logging and exiting, and consider circuit breakers or timeouts.

4. Define termination and safety conditions

Set a maximum number of iterations to prevent infinite loops, and optionally track visited locations to detect cycles if the API might return repeated positions.

5. Outline testing strategy

Plan unit tests with mocked API responses for success, errors, and edge cases (e.g., API returns same location repeatedly). Include integration tests if possible.

Key Points to Mention

  • API contract details: request/response format, error codes, rate limits
  • Retry logic with exponential backoff and jitter for transient failures
  • Termination conditions: destination reached, max steps, or unrecoverable error
  • State management: tracking visited locations to avoid cycles
  • Testing: mocking API responses for unit tests, covering success and failure paths
  • Observability: logging each step and errors for debugging

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

Q2

How would you make the maze traversal resumable if the process crashes midway?

System DesignTechnical Trade-offs
Author's notes

Saved by having done something similar at a previous job.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the maze traversal algorithm and the definition of 'resumable' (e.g., resume from exact state or approximate progress). Then propose a checkpointing mechanism that periodically persists the traversal state (current position, visited set, path stack) to durable storage, and on restart, load the latest checkpoint and continue. Discuss trade-offs between checkpoint frequency, storage overhead, and recovery time.

Pro tip: Emphasize idempotency and consistency: ensure that resuming from a checkpoint does not re-process nodes or miss nodes, and consider using a write-ahead log for atomic checkpoint updates. Also, mention that the checkpoint should include enough context to reconstruct the algorithm's state, not just the current position.

1. Clarify requirements and constraints

Ask about the maze size, traversal algorithm (DFS, BFS, A*), expected crash frequency, and acceptable recovery time. This determines checkpoint granularity and storage choice.

2. Design checkpointing strategy

Decide what state to persist (current node, visited set, frontier/path stack, algorithm-specific data) and how often (e.g., every N steps or time-based). Choose a durable store like disk, database, or distributed cache.

3. Implement atomic checkpoint writes

Use techniques like write-ahead logging or double-buffering to ensure checkpoints are not corrupted if a crash occurs during writing. Version checkpoints to handle partial writes.

4. Handle recovery and resumption

On restart, load the latest valid checkpoint, validate its integrity, and resume traversal from that state. Ensure the algorithm can continue without redoing work or missing nodes.

5. Discuss trade-offs and optimizations

Balance checkpoint frequency vs. overhead, consider incremental checkpoints, and mention how to handle large visited sets (e.g., bloom filters or compression). Also address concurrency if multiple traversals run.

Key Points to Mention

  • Checkpoint contents: current position, visited nodes, path/frontier, and any algorithm-specific state (e.g., heuristic values).
  • Storage options: local disk, database, or distributed store; consider durability and latency.
  • Atomicity: use write-ahead logs or atomic file writes to avoid corrupted checkpoints.
  • Recovery process: load latest checkpoint, validate, and resume; handle missing or corrupt checkpoints gracefully.
  • Trade-offs: checkpoint frequency vs. performance overhead; recovery time vs. storage cost.
  • Idempotency: ensure resuming does not duplicate work or skip nodes, possibly by tracking processed edges.

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

Q3

How would you handle the case where multiple paths through the maze are possible and you want to explore them concurrently?

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

Blanked for a second.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem constraints (maze size, branching factor, goal definition) and then propose a concurrent exploration strategy using parallel BFS/DFS with proper synchronization. Discuss trade-offs between parallelism, memory, and complexity, and mention how you would handle shared state and termination detection.

Pro tip: Emphasize that concurrency introduces nondeterminism and overhead; a good engineer would first assess if parallelism is truly needed or if a single-threaded approach with optimizations suffices. If concurrent, use a work-stealing or frontier-based approach to balance load and avoid contention.

1. Clarify requirements and constraints

Ask about maze size, number of paths, performance goals, and whether the maze is static or dynamic. This determines if concurrency is beneficial and what synchronization is needed.

2. Choose a concurrent exploration model

Decide between parallel BFS (level-synchronous) or parallel DFS (task-based). For BFS, partition the frontier among threads; for DFS, use a work queue with dynamic task assignment.

3. Design shared state and synchronization

Use concurrent data structures (e.g., concurrent queue, atomic visited set) to track visited nodes and the frontier. Minimize locking with lock-free structures or fine-grained locks.

4. Handle termination and result aggregation

Implement termination detection (e.g., when all threads are idle and frontier is empty) and aggregate results (e.g., first path found, all paths, shortest path).

5. Analyze trade-offs and optimize

Discuss overhead of synchronization, potential for load imbalance, and alternatives like using a single-threaded approach with memoization. Suggest profiling to validate concurrency benefits.

Key Points to Mention

  • Parallel BFS with level-synchronous frontier expansion
  • Work-stealing or task-based parallelism for DFS
  • Concurrent data structures (e.g., ConcurrentLinkedQueue, ConcurrentHashMap) for visited set and frontier
  • Termination detection when all threads are idle and no new nodes are added
  • Trade-offs: speedup vs. synchronization overhead, memory usage, and complexity
  • Alternative: single-threaded with optimizations if concurrency overhead outweighs benefits

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

Q4

How would you observe and measure the latency and failure rate of the API calls during traversal?

API & IntegrationsSystem Design
Author's notes

Pretty standard observability question.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the traversal context (e.g., graph traversal, service dependency traversal) and the API call patterns. Then describe a layered observability strategy: instrument each call with metrics, logs, and traces; aggregate them to compute latency percentiles and failure rates; and set up dashboards and alerts for real-time monitoring. Emphasize how you would use these measurements to detect anomalies and improve system reliability.

Pro tip: Mention that you would measure latency at multiple points (client-side, server-side, and network) to isolate bottlenecks, and use histograms rather than averages to capture tail latencies that impact user experience.

1. Clarify scope and define metrics

Confirm what 'traversal' means in this context (e.g., graph traversal, service mesh traversal) and identify the specific API calls involved. Define the key metrics: latency (p50, p95, p99) and failure rate (error percentage, error types).

2. Instrument the calls

Add instrumentation to each API call using libraries like OpenTelemetry, Prometheus client, or custom middleware. Capture start/end timestamps, status codes, and error details. Ensure correlation IDs are propagated for distributed tracing.

3. Collect and aggregate data

Send metrics to a time-series database (e.g., Prometheus, Datadog) and logs to a centralized system (e.g., ELK, Loki). Use histograms for latency and counters for failures. Aggregate data by service, endpoint, and traversal path.

4. Visualize and alert

Create dashboards (e.g., Grafana) showing latency percentiles and failure rates over time, broken down by relevant dimensions. Set up alerts for thresholds (e.g., p99 latency > 500ms, error rate > 1%) to proactively detect issues.

5. Analyze and iterate

Use the data to identify bottlenecks and failure patterns. Correlate with traces to pinpoint root causes. Continuously refine instrumentation and thresholds based on findings and changing requirements.

Key Points to Mention

  • Use of distributed tracing (e.g., OpenTelemetry, Jaeger) to follow requests across services and measure per-hop latency.
  • Importance of measuring latency percentiles (p50, p95, p99) instead of averages to capture tail latencies.
  • Failure rate calculation: total errors divided by total requests, segmented by error type (e.g., timeouts, 5xx, 4xx).
  • Instrumentation strategies: middleware, service mesh (e.g., Istio), or API gateways for automatic metrics collection.
  • Alerting and SLOs: define service level objectives for latency and error rates, and alert when violated.
  • Consideration of external dependencies: monitor third-party API latency and failures separately.

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