← Lyft Interview Insights

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

SeniorPrefer not to say
Jun 2026

Summary

Lyft system design round focused entirely on a pagination API problem. Pretty deep dive, more than I expected for a single question.

Questions Asked (1)

Q1

You have a large table of transaction records with fields like id, userId, amount, and createdAt. Design APIs to fetch transactions in reverse chronological order with pagination. You need to support both offset-based and cursor-based pagination using (createdAt, id) as the cursor. The response should include metadata like hasNext, nextCursor, and total count for offset mode. Also handle timestamp ties, and explain how you'd keep results stable when new records are inserted between page requests.

System DesignAPI & IntegrationsTechnical Trade-offs
Author's notes

The cursor-based part is where I spent most of my time and honestly where things got interesting.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and constraints, then design the API endpoints with clear parameters and response structures for both pagination modes. Explain the cursor encoding using (createdAt, id) and how it ensures stable ordering, and discuss strategies to handle timestamp ties and data consistency.

Pro tip: Emphasize the importance of a composite index on (userId, createdAt, id) for efficient querying and stable ordering, and mention that cursor-based pagination is generally preferred for large datasets due to its consistency and performance.

1. Clarify Requirements and Constraints

Ask about expected data volume, query patterns, consistency requirements, and whether total count is needed for all modes. Confirm that transactions are per user and sorted by createdAt descending.

2. Design API Endpoints and Parameters

Define endpoints like GET /users/{userId}/transactions with query parameters: limit, offset (for offset mode), cursor (for cursor mode). Specify response structure including data array and metadata (hasNext, nextCursor, totalCount for offset mode).

3. Explain Cursor Encoding and Query Logic

Describe how to encode (createdAt, id) into an opaque cursor (e.g., base64 of JSON or concatenated string). Show the SQL query for cursor-based pagination using a WHERE clause that handles ties: (createdAt < :cursorCreatedAt) OR (createdAt = :cursorCreatedAt AND id < :cursorId).

4. Address Stability and Consistency

Discuss how cursor-based pagination avoids duplicates/skips when new records are inserted, while offset-based pagination may shift. Mention using a snapshot or consistent read if needed, and how to handle timestamp ties by including id in the cursor.

5. Discuss Trade-offs and Optimizations

Compare offset vs cursor pagination: offset is simple but inefficient for large offsets and unstable; cursor is efficient and stable but doesn't support random access. Mention indexing strategy and caching for total count.

Key Points to Mention

  • Composite index on (userId, createdAt DESC, id DESC) for efficient sorting and filtering.
  • Cursor encoding: base64 of JSON {createdAt, id} or a string like 'createdAt_id'.
  • Handling timestamp ties: include id in cursor and use OR condition in WHERE clause.
  • Stability: cursor-based pagination is stable against inserts; offset-based may skip/duplicate.
  • Metadata: hasNext determined by fetching limit+1; nextCursor from last item; totalCount only for offset mode (may be expensive).
  • Trade-offs: offset allows jumping to page N but is O(offset) and unstable; cursor is O(1) but sequential.

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