← Back to list

Algorithms Still Matter: Sliding Window in Real Software Systems

A common interview pattern becomes useful when production systems need to reason about recent behavior.

Alexander in Coffee☕ And Code💚 · 2026-06-17 23:36 · 26 claps · 4.4 min read
#system-engineering #python #algorithms #redis #system-design-concepts
Open on Medium ↗
Wiki topics: 💻 · Programming

Algorithms Still Matter: Sliding Window in Real Software Systems

A common interview pattern becomes useful when production systems need to reason about recent behavior.

Photo by Bozhin Karaivanov on Unsplash

Photo by Bozhin Karaivanov on Unsplash

Algorithms nowadays get reduced to interview preparation.

A sliding window is a good example. In interviews, it usually appears as a string or array problem: find the longest substring, calculate the maximum subarray sum, count elements within a moving window, etc.

It feels artificial.

But it’s not all about the pure algorithm — the same pattern appears in real systems whenever we ask a simple question:

How many relevant events happened recently?

That question shows up in login protection, rate limiting, abuse detection, monitoring, analytics, and background job processing.

The useful part of algorithms is not memorizing names and “correct” implementations for interviews. It is recognizing when a real system has the same shape as one of those patterns.

The real problem: recent events

Imagine we want to limit the rate of user login attempts.

A simple rule could be:

If the same user has more than five failed login attempts within five minutes, slow down further attempts or require an additional check.

A naive implementation might count all failed attempts:

failed_attempts[user_id] += 1

if failed_attempts[user_id] > 5:
    flag_user(user_id)

This is easy to write, but it does not express the actual rule.

Five failed attempts over six months and five failed attempts in thirty seconds are very different signals. The total count is not enough — the timing matters.

We do not care about how many times the user failed.

We want to know whether the user failed too many times recently.

That is a sliding-window problem.

A production-shaped implementation

The simplest teaching example would store timestamps in a local Python deque.

That explains the algorithm, but it is not enough for a production-grade application.

If the app runs on multiple pods or multiple servers, each process has its own memory. One process might see three failed attempts, another process might see three more, and neither would know the real total. A restart would also erase the state.

For a real system, the sliding window usually needs shared storage.

Redis is a common option because it supports fast writes, expiry, and sorted sets. We can store events in a sorted set where the score is the event timestamp.

Here is a reusable sliding-window counter:

import time
import uuid
import redis

r = redis.Redis(host="localhost", port=6379, decode_responses=True)

def sliding_window_count(key: str, window_seconds: int, limit: int) -> tuple[bool, int]:
    """
      Returns:
          allowed: whether the event is still within the limit
          count: number of events currently inside the window
    """ 
    now = time.time()
    window_start = now - window_seconds
    event_id = f"{now}:{uuid.uuid4()}"

    pipe = r.pipeline()

    # Add current event.
    pipe.zadd(key, {event_id: now})

    # Remove old events outside the window.
    pipe.zremrangebyscore(key, 0, window_start)

    # Count events inside the window.
    pipe.zcard(key) 

    # Expire the key so Redis eventually cleans it up.
    pipe.expire(key, window_seconds + 60)

    _, _, count, _ = pipe.execute()

    return count <= limit, count

This implementation has a few useful properties:

  • The state is shared across application workers;
  • old events are removed;
  • Unused keys expire automatically;
  • The same function can be reused for different rules.

There is still one important caveat: under high concurrency, this should be wrapped in a Redis Lua script so the add, cleanup, and count happen atomically. The example above is useful because it clearly shows the structure, not because it is the final form of every production rate limiter.

Example 1: failed login attempts

Now the login rule becomes small and explicit:

def check_failed_login(user_id: str) -> bool:
    allowed, count = sliding_window_count(
        key=f"failed_login:user:{user_id}",
        window_seconds=5 * 60,
        limit=5
    )

    return allowed

If allowed is False, the product action depends on the system. You might slow down the next attempt, require CAPTCHA, temporarily lock the account, or trigger an alert.

The important part is that the decision is based on recent behavior.

We can also track the same event by IP address:

def check_failed_login_from_ip(ip_address: str) -> bool:
    allowed, count = sliding_window_count(
        key=f"failed_login:ip:{ip_address}",
        window_seconds=5 * 60,
        limit=5
    )

    return allowed

The user-based rule catches attacks targeting a single account. The IP-based rule catches a single source attacking multiple accounts.

Same algorithm. Different key. Different product meaning.

Example 2: API rate limiting

Another common use case is API rate limiting.

For example:

Allow each API key up to 100 requests per minute.

def check_api_rate_limit(api_key: str) -> bool:
    allowed, count = sliding_window_count(
        key=f"failed_login:ip:{ip_address}",
        window_seconds=60,
        limit=100
    )

    return allowed

Again, the point is not the Redis call itself. The point is the rule we are expressing.

The system is not asking whether this API key has exceeded the total number of requests. It is asking whether it made too many requests inside the current one-minute window.

That distinction matters. A client can recover after a burst instead of being blocked forever.

Example 3: abuse detection

Sliding windows are useful whenever we care about bursts of behavior.

For example:

A user should not send more than 20 messages in one minute.

def check_message_limit(user_id: str) -> bool:
    allowed, count = sliding_window_count(
        key=f"messages:user:{user_id}",
        window_seconds=60,
        limit=20
    )

    return allowed

This is a good example of why algorithmic thinking matters.

The system is not saying, “This user has sent many messages in their lifetime.” It is saying, “This user is sending too many messages right now.”

That is a different decision, and it leads to different product behavior.

The common shape

All examples above use the same structure:

allowed, count = sliding_window_count(
    key="some:event:scope",
    window_seconds=some_window,
    limit=some_limit,
)

Only three things change:

  1. the event — failed login, API request, message, error;
  2. the scope — user, IP address, API key, service;
  3. the window and limit — ten minutes, one minute, five minutes.

That is why the sliding-window pattern is useful. It gives us a reusable way to express rules based on recent behavior.

The implementation can change with scale. An in-memory queue may be enough for a toy script. Redis may work for a small production system. A larger system may need Lua scripts, distributed counters, streams, or a dedicated rate-limiting service.

But the shape stays the same:

Keep recent events. Remove old ones. Decide based on what remains.

Final thoughts

Algorithms still matter in software engineering because real systems continue to make decisions.

What should be blocked? What should be delayed? What should be counted? What should be ignored? Which events still matter, and which ones are too old to matter?

A sliding window is not just an interview trick. It is a practical way to reason about recent behavior in real software systems.

The value is not in memorizing the pattern name. The value is in recognizing when a real system has that shape.


메타데이터
post_id
ca979fd7ffed
slug
algorithms-still-matter-sliding-window-in-real-software-systems-ca979fd7ffed
url
https://medium.com/techtrends-digest/algorithms-still-matter-sliding-window-in-real-software-systems-ca979fd7ffed
canonical_url
https://medium.com/techtrends-digest/algorithms-still-matter-sliding-window-in-real-software-systems-ca979fd7ffed
author_url
https://medium.com/@lexpank
status
ok
fetched_at
2026-06-21 07:44:09