Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ def expensive_api_call(user_id: int):

</details>

<details>
<summary><strong>Memcached — Optional</strong></summary>

```python notest
from cachekit import cache
from cachekit.backends.memcached import MemcachedBackend

# pip install cachekit[memcached]

backend = MemcachedBackend() # Defaults to 127.0.0.1:11211

@cache(backend=backend)
def expensive_api_call(user_id: int):
return fetch_user_data(user_id)
```

*Requires: `pip install cachekit[memcached]` or `uv add cachekit[memcached]`*

</details>

---

> **CachekitIO Cloud (Alpha)**
Expand Down Expand Up @@ -175,8 +195,8 @@ def test_cached_function():
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ L1 Cache (In-Memory) │ L2 Cache (Pluggable Backend) │
│ ~50ns │ Redis / CachekitIO / File
│ │ ~2-50ms
│ ~50ns │ Redis / CachekitIO / File /
│ │ Memcached ~2-50ms │
├─────────────────────────────────────────────────────────────┤
│ Rust Core (PyO3) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
Expand All @@ -198,7 +218,7 @@ def test_cached_function():
- Circuit breaker with graceful degradation
- Connection pooling with thread affinity (+28% throughput)
- Distributed locking prevents cache stampedes
- Pluggable backend abstraction (Redis, CachekitIO, File, HTTP, DynamoDB, custom)
- Pluggable backend abstraction (Redis, CachekitIO, File, Memcached, custom)

> [!NOTE]
> All reliability features are **enabled by default** with `@cache.production`. Use `@cache.minimal` to disable them for maximum throughput.
Expand Down Expand Up @@ -351,6 +371,12 @@ REDIS_URL="redis://localhost:6379" # Fallback
CACHEKIT_API_KEY="your-api-key" # Required for @cache.io() # pragma: allowlist secret
CACHEKIT_API_URL="https://api.cachekit.io" # Default SaaS endpoint

# Memcached Backend (optional: pip install cachekit[memcached])
CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]' # Default: 127.0.0.1:11211
CACHEKIT_MEMCACHED_CONNECT_TIMEOUT=2.0 # Default: 2.0 seconds
CACHEKIT_MEMCACHED_TIMEOUT=1.0 # Default: 1.0 seconds
CACHEKIT_MEMCACHED_KEY_PREFIX="myapp:" # Default: "" (none)

# Optional Configuration
CACHEKIT_DEFAULT_TTL=3600
CACHEKIT_MAX_CHUNK_SIZE_MB=100
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Cache to the edge with `@cache.io` - no Redis to manage:
| Guide | Description |
|:------|:------------|
| [Serializer Guide](guides/serializer-guide.md) | Choose the right serializer for your data |
| [Backend Guide](guides/backend-guide.md) | Custom storage backends (Redis, HTTP, DynamoDB) |
| [Backend Guide](guides/backend-guide.md) | Storage backends (Redis, CachekitIO, File, Memcached, custom) |

<details>
<summary><strong>Serializer Options</strong></summary>
Expand Down
2 changes: 1 addition & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ For error examples and handling patterns, see [Troubleshooting Guide](troublesho

## Backend Abstraction

cachekit uses a protocol-based backend abstraction (PEP 544) that allows pluggable storage backends for L2 cache. While Redis is the default, you can implement custom backends for HTTP APIs, DynamoDB, file storage, or any key-value store.
cachekit uses a protocol-based backend abstraction (PEP 544) that allows pluggable storage backends for L2 cache. Built-in backends include Redis, CachekitIO, File, and Memcached. You can also implement custom backends for any key-value store.

For comprehensive backend guide with examples and implementation patterns, see **[Backend Guide](guides/backend-guide.md)**.

Expand Down
4 changes: 2 additions & 2 deletions docs/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ sequenceDiagram

**Why cachekit wins**:
- **Same code**: `@cache` decorator works with or without Redis
- **Pluggable backends**: Redis included, but can add Memcached, DynamoDB, HTTP, etc.
- **Pluggable backends**: Redis, CachekitIO, File, Memcached built-in, plus custom protocol
- **Graceful degradation**: Redis down? L1 cache serves, app continues
- **No vendor lock-in**: Backend protocol is documented, implement your own

Expand Down Expand Up @@ -503,7 +503,7 @@ A: Yes. Works with any framework (FastAPI, Django, Flask, etc). Metrics integrat
A: Circuit breaker catches errors, returns stale cache or None, app continues working.

**Q: Can I use my own backend?**
A: Yes. Implement the BaseBackend protocol (~100 LOC) for custom storage (DynamoDB, HTTP, Memcached, etc).
A: Yes. Four built-in backends (Redis, CachekitIO, File, Memcached) or implement the BaseBackend protocol (~100 LOC) for custom storage.

---

Expand Down
33 changes: 31 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@

## Backend Options

cachekit supports three backends. Pick the one that fits your infrastructure:
cachekit supports four backends. Pick the one that fits your infrastructure:

| Backend | Best For | Required Config |
|---------|----------|----------------|
| Redis | Self-hosted, full control | `CACHEKIT_REDIS_URL` |
| CachekitIO | Managed, zero-ops | `CACHEKIT_API_KEY` |
| File | Local dev, testing | None |
| Memcached | High-throughput, existing infra | `CACHEKIT_MEMCACHED_SERVERS` |

**Redis is the recommended default.** CachekitIO is a managed alternative (currently in closed alpha). File backend is intended for local development and testing only.
**Redis is the recommended default.** CachekitIO is a managed alternative (currently in closed alpha). File backend is intended for local development and testing only. Memcached is an optional backend (`pip install cachekit[memcached]`).

### Redis Backend

Expand Down Expand Up @@ -47,6 +48,14 @@ File-based cache for local development and testing. No external services require

**Configuration:** See the [File Backend](#file-backend-environment-variables) section below.

### Memcached Backend

> Requires: `pip install cachekit[memcached]`

High-throughput in-memory caching with consistent hashing across multiple servers.

**Configuration:** See the [Memcached Backend](#memcached-backend-environment-variables) section below.

---

## Environment Variables
Expand Down Expand Up @@ -164,6 +173,26 @@ CACHEKIT_FILE_MAX_ENTRY_COUNT=10000
CACHEKIT_FILE_LOCK_TIMEOUT_SECONDS=5.0
```

### Memcached Backend Environment Variables

> Requires: `pip install cachekit[memcached]` or `uv add cachekit[memcached]`

```bash
# Server list (JSON array format, default: ["127.0.0.1:11211"])
CACHEKIT_MEMCACHED_SERVERS='["mc1:11211", "mc2:11211"]'

# Timeouts
CACHEKIT_MEMCACHED_CONNECT_TIMEOUT=2.0 # Default: 2.0 seconds (range: 0.1-30.0)
CACHEKIT_MEMCACHED_TIMEOUT=1.0 # Default: 1.0 seconds (range: 0.1-30.0)

# Connection pool
CACHEKIT_MEMCACHED_MAX_POOL_SIZE=10 # Default: 10 per server (range: 1-100)
CACHEKIT_MEMCACHED_RETRY_ATTEMPTS=2 # Default: 2 (range: 0-10)

# Optional key prefix for namespace isolation
CACHEKIT_MEMCACHED_KEY_PREFIX="myapp:" # Default: "" (none)
```

---

## L1 Cache Configuration
Expand Down
4 changes: 2 additions & 2 deletions docs/data-flow-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ cachekit uses a hybrid Python-Rust architecture to provide enterprise-grade cach
> [!TIP]
> **Architecture Principles:**
> - **L1 + L2 Caching**: In-memory bytes cache (L1) + pluggable backend storage (L2) for optimal performance
> - **Backend Abstraction**: Protocol-based L2 backend layer (Redis, HTTP, DynamoDB, etc.)
> - **Backend Abstraction**: Protocol-based L2 backend layer (Redis, CachekitIO, File, Memcached, custom)
> - **Bytes-Only Storage**: L1 stores serialized bytes (encrypted or plaintext msgpack), not Python objects
> - **Security First**: Decompression bomb protection, checksum validation, size limits, encrypted-at-rest
> - **Performance Optimized**: Thread affinity, connection pooling, pre-cached serializers
Expand Down Expand Up @@ -492,7 +492,7 @@ class BaseBackend(Protocol):
- **Bytes-only interface**: Language-agnostic, no Python-specific types
- **Stateless operations**: No connection management in protocol
- **Simple and focused**: Four operations only (get/set/delete/exists)
- **Works for any backend**: Redis, HTTP, DynamoDB, local file storage, etc.
- **Works for any backend**: Redis, CachekitIO, File, Memcached, custom implementations

### RedisBackend (Default Implementation)

Expand Down
25 changes: 24 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,13 @@ export CACHEKIT_API_KEY=ck_your_api_key

## Choose Your Backend

Three paths depending on your situation:
Four paths depending on your situation:

| Backend | When to use | Setup effort |
|:--------|:------------|:-------------|
| **Redis** (recommended) | Production, existing infra, full control | Medium — run Redis yourself |
| **CachekitIO Cloud** (alpha) | Skip Redis ops, managed edge caching | Low — API key only |
| **Memcached** (optional) | High-throughput, existing Memcached infra | Low — `pip install cachekit[memcached]` |
| **File / L1-only** | Local dev, tests, no external deps | None |

### Redis (Recommended)
Expand Down Expand Up @@ -284,6 +285,28 @@ def get_user(user_id: int):

Everything else — TTL, namespaces, serializers — works the same as with Redis. Swap `@cache` for `@cache.io()` and you're done.

### Memcached (Optional)

High-throughput in-memory caching with consistent hashing. No persistence — data is lost on restart.

```bash
pip install cachekit[memcached]
# Default: connects to 127.0.0.1:11211
```

```python notest
from cachekit import cache
from cachekit.backends.memcached import MemcachedBackend

backend = MemcachedBackend()

@cache(backend=backend, ttl=3600)
def get_user(user_id: int):
return fetch_from_db(user_id)
```

Everything else — TTL, namespaces, serializers — works the same as with Redis. See the [Backend Guide](guides/backend-guide.md) for multi-server configuration.

### File / L1-Only (Dev and Testing)

No external dependencies. Pure in-process memory cache. Not suitable for multi-pod or production.
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/backend-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Implement custom storage backends for L2 cache beyond the default Redis.

## Overview

cachekit uses a protocol-based backend abstraction (PEP 544) that allows pluggable storage backends for L2 cache. While Redis is the default, you can implement custom backends for HTTP APIs, DynamoDB, file storage, or any key-value store.
cachekit uses a protocol-based backend abstraction (PEP 544) that allows pluggable storage backends for L2 cache. Four backends are included: Redis (default), CachekitIO (managed SaaS), File (local storage), and Memcached (optional). You can also implement custom backends for any key-value store.

**Key insight**: Backends are completely optional. If you don't specify a backend, cachekit uses RedisBackend with your configured Redis connection.

Expand Down
Loading