Project History

coredis is a fork of the excellent aredis client developed and maintained by Jason Chen.

aredis already had support for cluster & sentinel and was one of the best performing async python clients. Since it had become unmaintained as of October 2020 The initial intention of the fork was add python 3.10 compatibility and v2.0.0 was drop-in backward compatible with aredis and addd support up to python 3.10.

Version v6.0.0rc1 was a large scale refactor that replaced all internal async task management and io with anyio (contributed by Graeme Holliday) This essentially enables the library to be used with trio.

Divergence from aredis & redis-py

Versions v3.0.0 and above no longer maintain compatibility with aredis. Since aredis mostly mirrored the redis client, this inherently means that coredis diverges from both, most notable (at the time of writing) in the following general categories:

  • API signatures for redis commands that take variable length arguments are only variadic if they are optional, for example coredis.Redis.delete() takes a variable number of keys however, they are not optional. Thus the signature expects a collection of keys as the only positional argument

    Redis.delete(keys: Parameters[KeyT]) CommandRequest[int]

    Delete one or more keys.

    Parameters:

    keys – One or more key names to delete.

    Returns:

    The number of keys that were removed.

    Redis command documentation: CommandName.DEL

  • Redis commands that accept tokens for controlling behavior now use PureToken and the coredis methods mirroring the commands use Literal to document the acceptable values. An example of this is coredis.Redis.expire().

    Redis.expire(key: KeyT, seconds: int | timedelta, condition: Literal[PureToken.NX, PureToken.XX, PureToken.GT, PureToken.LT] | None = None) CommandRequest[bool]

    Set a key’s time to live in seconds.

    Parameters:
    • key – The key name.

    • seconds – TTL in seconds (or timedelta).

    • condition – Optional NX, XX, GT, or LT.

    Returns:

    True if the timeout was set, False otherwise (e.g. key does not exist).

    Redis command documentation: CommandName.EXPIRE

    Compatibility:

  • Since v3.0.0 building an async redis client with strict type hints for all APIs has been one of the primary goals of the project. As of v5.0.0 all clients (including pipelines) were correctly statically typed and the use of type stubs was completely eliminated.

  • As of v5.0.0 all core redis command methods exposed by the Clients were changed from coroutines to regular methods that return CommandRequest objects which are of type Awaitable.

  • coredis takes a significantly different approach to connection pooling than redis & aredis to optimize performance in an async context. In the simplest terms, the connection pool will only grow beyond 1 connection per target server (cluster connection pools maintain sub pools for every node in the cluster) if the connection has been acquired in a blocking request. For all non blocking requests coredis will pipeline concurrent requests on the same connection which will get resolved asynchronously. This significantly reduces the connection cost and inherently improves performance.

  • coredis almost always tries to provide a simply pythonic 1:1 mapping of command parameters from the redis specification which means that higher level abstractions are rarely provided. This is signficantly different from the approach redis takes, especially with respect to Redis Modules support. See the RediSearch search() method as an example. For complex patterns such as Pub/Sub, Pipelining and Streams however, light abstractions are provided. See Handbook for more details.

Default RESP3

v3.0.0 supported selecting the protocol version to use when parsing responses from the redis server and defaulted to the legacy RESP protocol. Since coredis has dropped support for redis server versions below 6.0 the default protocol version is now RESP3.

Parsers

coredis versions 2.x and 3.x would default to a hiredis based parser if the dependency was available. This behavior was inherited from aredis which inherited it from redis. Though hiredis does provide a significant speedup when parsing responses for large nested bulk responses, coredis has made sufficient improvements in performance including using mypyc to provide a native speedup when possible and therefore no longer supports multiple parser implementations and always uses coredis.parser.Parser.