hitbox 0.2.0

Asynchronous caching framework.
Documentation

Hitbox

Highly customizable async caching framework for Rust designed for high-performance applications.

Hitbox is protocol-agnostic at its core, with first-class HTTP support via hitbox-http. It provides pluggable backends from in-memory (Moka) to distributed solutions (Redis). Built on Tower, it works with any tokio-based service.

Quick Start

If you need to add caching to your project, choose the appropriate integration based on your use case:

Use Case Crate Description
Server-side (Axum, Tower-based frameworks) hitbox-tower Tower middleware layer for HTTP handlers
Client-side (Hyper) hitbox-tower Tower middleware layer for hyper client
Client-side (Reqwest) hitbox-reqwest Cache responses from external APIs via reqwest-middleware

For detailed usage, see the documentation for these crates and the examples directory.

Understanding Hitbox

The Hitbox Ecosystem

Hitbox is organized as a collection of crates, each with a specific responsibility:

Crate Description
hitbox Main crate — re-exports core types, policy configuration, error types
hitbox-core Protocol-agnostic core traits ([Predicate], Extractor, [CacheableRequest], [CacheableResponse])
hitbox-backend Backend trait and utilities for implementing storage backends
hitbox-http HTTP-specific predicates and extractors for request/response caching
hitbox-tower Tower middleware (Cache layer) for server-side caching
hitbox-moka In-memory backend using Moka
hitbox-redis Distributed backend using Redis (single node and cluster)
hitbox-feoxdb Embedded persistent backend using FeOxDB
hitbox-reqwest Client-side caching for Reqwest via reqwest-middleware
hitbox-test Testing utilities including MockTime for deterministic cache tests

Core Principles

Under the hood, Hitbox uses a Finite State Machine (FSM) to orchestrate cache operations. The FSM operates with four abstract traits that make Hitbox extensible to any protocol:

Backend

A Backend is a storage where cached data lives. It can be:

  • In-memory — like Moka for single-instance, high-speed caching
  • Distributed — like Redis (single node or cluster) for shared caching across instances
  • Embedded — like FeOxDB for persistent local storage

If you need a backend for a database that isn't in our list, you can add it by implementing the Backend trait. See the hitbox-backend documentation for details.

Upstream

An Upstream is a source of data. It could be:

  • An HTTP handler in a web framework
  • An external API call via Reqwest or Hyper
  • Any async function that produces data

The FSM calls the Upstream when the cache misses (data not found in the Backend).

Predicate

A Predicate answers the question: "Should this request/response be cached?"

The easiest way to explain predicates is through HTTP examples:

Request predicates — We might want to cache requests that:

  • Have a specific HTTP method (e.g., only GET requests)
  • Match a particular path pattern
  • Do NOT contain a Cache-Control: no-cache header
  • Do NOT have a cache=false query parameter

Response predicates — We might want to cache responses that:

  • Have a successful status code (2xx)
  • Do NOT contain sensitive headers
  • Have a body smaller than a certain size

Predicates implement the [Predicate] trait, which takes a request or response and returns Cacheable or NonCacheable. They can be combined using AND (chaining), OR, and NOT logic.

Extractor

An Extractor creates the cache key from request components.

For HTTP, you might extract:

  • Method and path as the base key
  • Path parameters like {user_id} from /api/users/{user_id}
  • Query parameters like page or limit that affect the response
  • Headers like Accept-Language for localized content

Multiple extractors can be chained together, each contributing parts to the final cache key.

Example: For a request to GET /api/users/123/posts?page=2 with Accept-Language: en, an extractor configured for method, path params, query, and headers would produce a key containing: ["GET", "123", "2", "en"].