algor.ist experiment · live Redis

The async Redis client
Python actually deserves.

coredis is a fast, fully typed Redis client built on structured concurrency. Cluster, Sentinel, pipelines, client-side caching, streams, and OpenTelemetry — without the footguns of half-async ports.

  • Fully typedpipelines · scripts · modules
  • anyioasyncio + trio
  • Tracking cacheserver-assisted
  • Redis ≥ 7cluster · sentinel · stack
showcase.py
import anyio
import coredis
from coredis.cache import LRUCache

async def main() -> None:
    client = coredis.Redis(
        cache=LRUCache(max_keys=4096),
        decode_responses=True,
    )
    async with client:
        await client.set("hello", "coredis")
        async with client.pipeline() as pipe:
            pipe.incr("hits")
            name = pipe.get("hello")  # Awaitable[str|None]
        print(await name)

anyio.run(main, backend="asyncio")

Live against Redis

Head-to-head demos

Each run executes real commands on a local Redis instance via this showcase’s Python backend — coredis on one side, redis.asyncio on the other. Numbers reflect this machine, this moment; the point is the shape of the difference.

Deep dives

Why coredis wins in practice

Performance is one axis. Typing, topology, caching, and runtime flexibility are the reasons teams stop fighting their Redis client.

Feature matrix

coredis vs the usual suspects

Capability coredis redis-py asyncio legacy aioredis
Native async design Yes (anyio) Port of sync API Unmaintained / merged
Strict type annotations Full public API Partial Weak
Typed pipeline futures Per-command list from execute() list
Client-side caching TrackingCache DIY DIY
asyncio + trio anyio asyncio only asyncio only
Cluster + Sentinel First-class Supported Partial
Redis modules / Stack Handbook support Via raw commands Limited
OpenTelemetry coredis[otel] External
Runtime type checks beartype optional
Native extensions (wheels) Bulk response speed hiredis optional hiredis

Typical asyncio jobs

Use cases where the client choice compounds

Session & feature-flag stores

Hot keys, read-mostly, latency-sensitive. Client-side caching turns Redis into an invalidated local map instead of a tax on every request.

cache=LRUCache(...) + GET/SET/EXPIRE

API rate limiting

INCR + EXPIRE or token buckets under concurrent workers. Typed commands and predictable pool behavior matter when every request touches Redis.

INCR · LUA · pipelines

Job queues & Streams

Consumer groups, acks, reclaim of pending entries. High-level stream helpers beat yet another fragile XREADGROUP loop.

XREADGROUP · XACK · consumers

Pub/Sub fan-out

Live notifications in asyncio services. Clean subscribe abstractions and structured cancel scopes (anyio) avoid zombie listeners.

SUBSCRIBE · PSUBSCRIBE

Cache-aside with Cluster

Multi-key pitfalls and MOVED redirects should be the client’s problem. One API from laptop Redis to production cluster.

RedisCluster · pipelines

Observability-first services

Trace Redis commands next to HTTP spans. Optional OTel integration without wrapping every call site by hand.

coredis[otel]

Try it

Get started in two minutes

Install

pip install coredis
# or
uv add coredis

Minimal asyncio

import asyncio
import coredis

async def main():
    r = coredis.Redis(decode_responses=True)
    async with r:
        await r.set("msg", "hi")
        print(await r.get("msg"))

asyncio.run(main())

Run this showcase

cd experiments/coredis
uv sync
# Redis on :6379 (or: docker compose up redis -d)
uv run uvicorn showcase.main:app --reload --port 8080

Official docs: coredis.readthedocs.io · Source: github.com/alisaifee/coredis