Visit-Pattern Counter: Multi-Input Runtime Analysis and Production Hardening

Read the full interview experience this question came from →

Quick Overview

A Spotify backend coding follow-up: for a function that finds the three-website visit pattern followed by the most distinct users, analyze time and memory using separate input dimensions such as records, users, longest per-user history and distinct sites. It also asks which functional and style changes the code needs before it ships in production.

Visit-Pattern Counter: Multi-Input Runtime Analysis and Production Hardening

Company: Spotify

Role: Backend Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Onsite

In a backend coding round, once you have a working function for the problem below, the interviewer spends the remaining time on follow-ups about what it costs and how you would get it ready for production code. **The function.** You receive three lists of equal length, `usernames`, `timestamps` and `websites`. Record `i` says that user `usernames[i]` visited website `websites[i]` at time `timestamps[i]`, and the records arrive in no particular order. A **pattern** is an ordered list of three website names, repeats allowed (`["home", "home", "cart"]` is valid). A user **follows** a pattern if its three websites appear in that order, not necessarily next to each other, in that user's visits sorted by time. A pattern's **score** is the number of distinct users who follow it. The function returns the highest-scoring pattern; among tied patterns it returns the lexicographically smallest, comparing the first names, then the second, then the third. Begin by stating the approach your implementation uses, since both follow-ups depend on it. ### Clarifying Questions - Can one user have two visits with the same timestamp, and if so, which one counts as earlier? - What should the function do when no user has at least three visits? - Will callers always want patterns of length three? - How are records typically distributed: many users with short histories, or a few users with very long ones, and how many distinct websites are there? ### Part 1 — Runtime and memory across the inputs The problem has several independent inputs, so a single n hides where the cost comes from. Express the time and memory of your approach in terms of the total number of records, the number of distinct users, the longest single-user history and the number of distinct website names. Say which term dominates, which input shape is the worst case, and how the cost changes when the same records are spread over many users instead of concentrated in one. Then explain what you would change if one user's history could be far longer than the number of distinct websites that user visits. ```hint Work per user first Write down the cost for a single user with a given number of visits, then add it up over users whose visit counts sum to the total. ``` #### What This Part Should Cover - The cost of each phase (grouping and ordering, pattern generation, counting, choosing the winner) in the named dimensions - How the dominant term behaves as records are spread out or concentrated, and the worst-case input shape - Bounds on the number of distinct patterns that come from the website vocabulary as well as from history length - Whether per-user work can depend on distinct websites rather than visit count, and when that is worth the extra code ### Part 2 — Changes before it ships in production code The team wants to merge your function into a production codebase. Describe the functional changes (interface, return value, input handling, behavior on edge cases) and the style changes (naming, decomposition, typing, documentation, tests) you would make, and give the reason for each. ```hint List the silent assumptions Every guarantee the interview version took for granted has to become a validation, a documented policy, or part of a type. ``` #### What This Part Should Cover - Interface and return-type changes that remove silent preconditions - Explicit policies for ambiguous input, with the tie rule kept deterministic - Decomposition and naming that make each step testable on its own - A test plan, including how any optimized path is checked against a simple reference ### What a Strong Answer Covers - Complexity stated in consistently named dimensions, with a justified worst-case input shape - Distinct-user counting and the tie rule preserved by every proposed change - Trade-offs between simpler code and a faster per-user step, tied to the expected input shapes - Production changes motivated by concrete failure modes rather than generic style advice ### Follow-up Questions - If the visit log were too large for one machine, how would you split grouping, per-user pattern extraction and counting across workers while keeping the tie rule deterministic? - How do the analysis and the code change if callers need patterns of length k instead of three? - Should the function return every tied pattern instead of one, and what would that change for callers?

Overview: A Spotify backend coding follow-up: for a function that finds the three-website visit pattern followed by the most distinct users, analyze time and memory using separate input dimensions such as records, users, longest per-user history and distinct sites. It also asks which functional and style changes the code needs before it ships in production.

Read the full Spotify Backend Engineer interview experience this question came from

Spotify logo
Spotify
Jul 7, 2026
mediumBackend EngineerOnsiteSoftware Engineering Fundamentals
0
0

In a backend coding round, once you have a working function for the problem below, the interviewer spends the remaining time on follow-ups about what it costs and how you would get it ready for production code.

The function. You receive three lists of equal length, usernames, timestamps and websites. Record i says that user usernames[i] visited website websites[i] at time timestamps[i], and the records arrive in no particular order. A pattern is an ordered list of three website names, repeats allowed (["home", "home", "cart"] is valid). A user follows a pattern if its three websites appear in that order, not necessarily next to each other, in that user's visits sorted by time. A pattern's score is the number of distinct users who follow it. The function returns the highest-scoring pattern; among tied patterns it returns the lexicographically smallest, comparing the first names, then the second, then the third.

Begin by stating the approach your implementation uses, since both follow-ups depend on it.

Clarifying Questions Guidance

  • Can one user have two visits with the same timestamp, and if so, which one counts as earlier?
  • What should the function do when no user has at least three visits?
  • Will callers always want patterns of length three?
  • How are records typically distributed: many users with short histories, or a few users with very long ones, and how many distinct websites are there?

Part 1 — Runtime and memory across the inputs

The problem has several independent inputs, so a single n hides where the cost comes from. Express the time and memory of your approach in terms of the total number of records, the number of distinct users, the longest single-user history and the number of distinct website names. Say which term dominates, which input shape is the worst case, and how the cost changes when the same records are spread over many users instead of concentrated in one. Then explain what you would change if one user's history could be far longer than the number of distinct websites that user visits.

What This Part Should Cover Guidance

  • The cost of each phase (grouping and ordering, pattern generation, counting, choosing the winner) in the named dimensions
  • How the dominant term behaves as records are spread out or concentrated, and the worst-case input shape
  • Bounds on the number of distinct patterns that come from the website vocabulary as well as from history length
  • Whether per-user work can depend on distinct websites rather than visit count, and when that is worth the extra code

Part 2 — Changes before it ships in production code

The team wants to merge your function into a production codebase. Describe the functional changes (interface, return value, input handling, behavior on edge cases) and the style changes (naming, decomposition, typing, documentation, tests) you would make, and give the reason for each.

What This Part Should Cover Guidance

  • Interface and return-type changes that remove silent preconditions
  • Explicit policies for ambiguous input, with the tie rule kept deterministic
  • Decomposition and naming that make each step testable on its own
  • A test plan, including how any optimized path is checked against a simple reference

What a Strong Answer Covers Guidance

  • Complexity stated in consistently named dimensions, with a justified worst-case input shape
  • Distinct-user counting and the tie rule preserved by every proposed change
  • Trade-offs between simpler code and a faster per-user step, tied to the expected input shapes
  • Production changes motivated by concrete failure modes rather than generic style advice

Follow-up Questions Guidance

  • If the visit log were too large for one machine, how would you split grouping, per-user pattern extraction and counting across workers while keeping the tie rule deterministic?
  • How do the analysis and the code change if callers need patterns of length k instead of three?
  • Should the function return every tied pattern instead of one, and what would that change for callers?