Skip to main content

flightlock banner

CI status PyPI version Python versions MIT License Code style: ruff Test coverage

GitHub stars Last commit Repo size Open issues Contributor Covenant

flightlock

Single-flight cache stampede protection for Python.

When a cached value expires under concurrent load, most caching libraries let every waiting request independently recompute it — hammering your database or API with N identical calls at once (a "cache stampede" or "thundering herd"). flightlock ensures only one caller recomputes the value while every other caller waits for and reuses that result.

Named after the "singleflight" pattern used in production caching systems (e.g. Go's golang.org/x/sync/singleflight, groupcache).

Table of contents

Why flightlock

Picture a cache key with a 60-second TTL backing an expensive DB query. The moment it expires, if 500 concurrent requests arrive for that key before it's repopulated, a naive cache sends all 500 straight to your database at once. flightlock coordinates those 500 callers so exactly one hits the database, and the other 499 wait milliseconds for that one result instead.

Quickstart

from flightlock import cached

@cached(ttl=60)
def get_user(user_id: int) -> dict:
    print("hitting the database...")
    return expensive_db_call(user_id)

get_user(1)  # prints "hitting the database...", takes 300ms
get_user(1)  # instant — cache hit, no print

With Redis and metrics enabled:

from flightlock import cached
from flightlock.backends.redis import RedisBackend

backend = RedisBackend(host="localhost", port=6379)

@cached(ttl=60, backend=backend, metrics=True)
def get_user(user_id: int) -> dict:
    return expensive_db_call(user_id)

Benchmark

Run it yourself: python benchmarks/stampede_benchmark.py

Simulating 200 concurrent requests for the same cache key, with a 0.3s simulated origin latency (e.g. a slow DB query):

Without Flightlock (Naive) With Flightlock
Origin Calls 200 1
Wall Time 0.309s 0.312s

Result: 9.5% fewer origin calls with flightlock (200 -> 1 calls for 200 concurrent requests)

Every request still returns the correct value — flightlock just ensures only one caller does the work while the other 199 wait for and share the result.

How it works

  1. A per-key lock registry tracks in-flight computations.
  2. When a caller arrives for a missing/expired key, it either becomes the leader (first arrival — runs the function) or a follower (waits for the leader's result).
  3. The leader runs the function outside the lock, so unrelated keys never block each other.
  4. When the leader finishes, every waiting follower is woken simultaneously and receives the same result (or the same exception, if it failed).

See src/flightlock/core.py for the implementation.

Features

  • ✅ Single-flight stampede protection (in-process)
  • ✅ Pluggable backends: in-memory, Redis
  • ✅ TTL jitter to prevent synchronized mass-expiry across many keys
  • ✅ Prometheus-compatible metrics (hits, misses, errors, latency)
  • ✅ Custom cache key functions
  • 🔜 Async support
  • 🔜 Cross-process distributed locking (currently: stampede protection is per-process; Redis backend shares storage across processes, not the lock)

Installation

pip install flightlock                  # core, zero dependencies
pip install flightlock[redis]           # + Redis backend
pip install flightlock[metrics]         # + Prometheus metrics
pip install flightlock[redis,metrics]   # everything

Comparison with alternatives

flightlock functools.lru_cache cachetools
Stampede protection
TTL support
Redis backend ❌ (needs extra glue)
TTL jitter
Metrics hook

flightlock isn't trying to replace general-purpose caching libraries — it solves one specific, real production problem (concurrent cache-miss stampedes) thoroughly.

Roadmap

  • Project scaffolding, CI, packaging config
  • Core single-flight lock implementation
  • In-memory backend
  • The @cached() decorator
  • TTL jitter
  • Redis backend
  • Metrics hook
  • Benchmark proving stampede protection under load
  • Publish to PyPI
  • Async support

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup instructions and guidelines.

Security

See SECURITY.md for how to report a vulnerability.

Support

See SUPPORT.md for how to get help.

AI-assisted development

This project was built with AI pair-programming assistance for scaffolding, boilerplate, and code review. See AI_POLICY.md for details on how AI was used and what was independently written, tested, and verified.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flightlock-0.1.1.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flightlock-0.1.1-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

Details for the file flightlock-0.1.1.tar.gz.

File metadata

  • Download URL: flightlock-0.1.1.tar.gz
  • Upload date:
  • Size: 21.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for flightlock-0.1.1.tar.gz
Algorithm Hash digest
SHA256 5a5abce180cc4335fcb16ff12bf20c34b9635e5ed82d1d844e00d0703e39ee6e
MD5 c07f9dc824fd40be9d65b13fbb62849c
BLAKE2b-256 bda459854db252881ce0be66f4cfe7e895324296de04aefbf6a6b033f255f2c8

See more details on using hashes here.

File details

Details for the file flightlock-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: flightlock-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 13.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for flightlock-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ddc01cff6bdc3cb13a4150a27c1e8663312bfb02c0dce9572b5117894b334226
MD5 e63cdb61449e92ef3e055412c9f90c49
BLAKE2b-256 9bc3b19764eb182d737c941a0b333c4ffaff2060fa4e06292f429fa55532509f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page