skip to content

In an inline login-risk scorer, what is a per-device velocity counter and why is it kept continuously updated?

level: juniorimportance: must knowfreq 58%

answer

  1. a count, not a model
  2. keyed by one entity
  3. recent window, not all time
  4. written by the stream, read by the scorer
  5. one flat lookup beats a scan

basics

~20 s

A per-device velocity counter is a running count of that device's recent login attempts, held in a low-latency key-value store and folded forward by the login event stream, so the inline scorer reads it in one lookup instead of scanning history.

solid answer

~40 s

A velocity counter is a count of how often something happened to one entity inside a recent window — for a device, how many login attempts or how many distinct accounts it touched in the last hour. It is kept as a running value in a low-latency key-value store, updated as login events arrive on the event stream, and read by key when a credential submit is being scored. It is maintained rather than computed because the inline scoring budget is a few tens of milliseconds: aggregating a device's history at request time means a range scan whose cost grows with that device's activity, which is exactly the traffic an attacker generates. One `lookup(key)` is flat-cost no matter how busy the entity is.

go deeper

for a junior

Be able to say what the counter counts, what it is keyed by, and that it is read in one lookup because the scorer runs inside the login request.

for a middle

Explain the write path and the read path separately: events fold into the store continuously, the scorer only reads, and the time-to-live is what bounds storage.

for a senior

Show that you pick entity keys for the attack you expect, and that you carry a short and a long window per entity because the useful signal is the ratio between them.

for a principal

Frame the counter set as the cheapest risk surface the organisation owns, and the one that must keep working when the model does not.

## What a velocity counter is A **velocity counter** is the simplest useful feature on a risk-scoring path: the number of times something happened to **one entity** inside a **recent time window**. It is arithmetic, not modelling — nothing about it is learned, and the same counter can feed a model input, a rule, or an operations dashboard without changing meaning. On a consumer login path three counters carry most of the signal, and saying **which counter** you mean is load-bearing because they catch different attacks: | counter key | example feature | what it catches | |---|---|---| | per account | failed logins for this account in the last 5 minutes | someone guessing one victim's password | | per device | distinct accounts this device attempted in the last hour | one client replaying a stolen credential list | | per source network | attempts from this network address in the last minute | a single origin fanning out across many accounts | A bare "the velocity counter" is ambiguous in a design round, and the interviewer is usually listening for whether you name the entity key. ## Why it is maintained instead of computed The scorer runs **inside** the credential submit, before the session is granted, on a hard budget of a few tens of milliseconds. That budget is what rules out computing the count from raw events when the request arrives. | approach | cost at request time | behaviour under attack | |---|---|---| | scan this entity's event history | grows with how active the entity is | worst exactly when the entity is hostile | | read a maintained counter by key | one lookup, flat | unchanged by attack volume | The second row is the whole argument. An attacker is, by definition, the busiest entity in the system; a design whose read cost scales with activity gets slowest precisely on the requests that matter most. ## How it is kept up to date 1. Login and session events — attempt, success, failure, password reset, device first-seen — are published to an **event stream** as they happen. 2. A **stream processor** (or, for the shortest windows, the scoring service itself) folds each event into a counter in a **low-latency key-value store**, keyed by entity and window. 3. Each counter carries a **time-to-live** matched to its window, so an entity that goes quiet ages out of the store instead of being swept by a separate job. 4. The scorer reads the counters it needs by key, in parallel, inside the feature-fetch stage of its budget. ## What the window means - A counter with a TTL is an approximation of a **sliding window**: it forgets the whole window at once rather than attempt by attempt. - An exact sliding count needs the individual timestamps kept per entity, which costs more storage and a more expensive read — real systems pick per feature, and some keep both a short exact window and a long approximate one. - Long windows (24 hours, 30 days) describe an entity's **baseline**; short windows (60 seconds, 5 minutes) describe what it is doing **right now**. Most login scorers carry both, because the interesting signal is usually the ratio between them. ## What a velocity counter is not - **Not a decision.** A high count is an input; whether a login is allowed, challenged or declined is decided further down the path. - **Not a rule.** "More than 20 attempts in a minute" is a rule expressed over a counter, but the counter itself asserts nothing. - **Not unique to fraud.** The same maintained-count pattern shows up wherever a read must be cheap and the underlying event volume is unbounded; here it happens to be the cheapest risk signal there is. ## What it costs - **Read cost:** one lookup per entity key per scored request. Three keys means a fan-out of three, and the stage's latency is the **slowest** of them, not the sum. - **Storage:** roughly one entry per active entity per window, bounded by the TTL rather than by total history. - **Write cost:** one increment per event, off the request path when the stream processor owns it. - **A lag:** the value the scorer reads is as fresh as the pipeline that wrote it, which matters once an attacker moves faster than that pipeline. Because it is this cheap and this legible, a velocity counter is usually the first feature a risk system ships and the last one it would give up — a fraud team that loses its model can still run on counters, which is why they double as the degraded path when scoring fails.

  • Why do login scorers usually keep both a 60-second and a 30-day counter for the same entity?
    The short window says what the entity is doing right now; the long window says what is normal for it. Ten attempts in a minute means something very different from a device that averages two logins a day than from a shared family tablet. Most of the signal is the ratio, so the two windows are separate features rather than one.
  • What happens to a counter for an entity that stops appearing entirely?
    It expires with its time-to-live and the key disappears, so the store holds roughly the active entity set rather than all history. The scorer must therefore treat a missing key as a genuine zero-or-unknown case with an explicit default, not as an error, because first-seen devices are common on a consumer login path.

A doorman who keeps a tally sheet per visitor rather than re-reading the whole guest book each time someone knocks: the tally is instant no matter how often that visitor has knocked today.

saying these in an interview costs you the question

  • Treating a velocity counter as a decision rather than an input
  • Saying the count is computed by querying the login log when the request arrives
  • Leaving the entity key unnamed, so account, device and network blur together
  • Assuming one long window is enough, with no short-window counter
  • Expecting a missing key to be an error rather than a first-seen entity