pymemcache: Pinterest's pure-Python client for memcached
A comprehensive, fast, pure-Python memcached client.
At a glance
- What is it?
- pymemcache is a memcached client written entirely in Python, covering the complete text protocol, connecting over UNIX sockets or TCP on IPv4 and IPv6, with separate connect and send timeouts, support for the noreply flag that skips write acknowledgements, and an optional mode where network and memcached errors count as cache misses. It is the client Django has shipped as its memcached backend since version 3.2.
- Who is it for?
- Adopt pymemcache when you want the memcached client to be pure Python, so it works under gevent and does not need libmemcached compiled against the right version. Do not choose it for the highest raw throughput on a stable platform, since a C wrapper will beat it.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the client covers and why pure Python is the point
pymemcache describes itself as a comprehensive, fast, pure-Python memcached client, and the feature list is short enough to read as a specification.
There is a complete implementation of the memcached text protocol, which matters because memcached also has a binary protocol and they are not interchangeable. Connections use UNIX sockets or TCP over IPv4 or IPv6. Timeouts are configurable separately for socket connect and for send and receive calls, which is a detail that matters more than it sounds, because a connect timeout and a read timeout have very different characteristics and a single timeout cannot cover both.
The noreply flag is the performance feature worth understanding. It tells memcached not to acknowledge a write, so the client can pipeline commands without waiting for a reply to each one. The README describes it as able to significantly increase the speed of writes, and it is the feature the competing pure-Python client does not have.
Serialization and deserialization is described as flexible, modular and simple, which is the design choice that lets the same client sit under different frameworks with different value types.
And the last feature is the one with the most design consequence: the optional ability to treat network and memcached errors as cache misses. That turns every failure into a silent empty result rather than an exception, which for a cache is often what you want, and which can also hide a misconfigured server for a long time.
The repository is Apache-2.0 licensed, the default branch is master, and the last push was on 2026-10-11. The tagged releases are v4.0.0 from 2022-10-17, v3.5.2 from 2022-04-01 and v3.5.1 from 2022-02-20, so the published versions are old while the branch is not, which is the state of many long-lived infrastructure libraries.
Installing it and running the tests
Installation is from pip:
pip install pymemcacheFor development, you clone and run the tests with tox:
git clone https://github.com/pinterest/pymemcache.git
cd pymemcachetoxThe README is specific that a local memcached server has to be running for the tests, which is the one setup step people miss. A pure-Python client against a real server is the right way to test a cache client, because the interesting bugs are in the protocol handling rather than in the object model.
The repository layout shows how a library of this age and this seriousness is organised. There is a pymemcache/ package directory, a docs/ directory, separate requirements files for docs, lint and mypy, a tox.ini for the test matrix, and both setup.py and setup.cfg alongside pyproject.toml. The setup.py is a three-line shim that calls setup(), with the real metadata in the configuration files.
The pyproject.toml holds tool configuration rather than package metadata: Black is configured with target versions from py39 through py314, and mypy runs against Python 3.9 with ignore_missing_imports enabled. The list of Black target versions is a good signal about which interpreters the project is expected to run on, and it runs from 3.9 to 3.14.
The ADOPTERS.md file at the root is a piece of housekeeping worth noticing. It exists so that when someone depends on pymemcache through a framework or a wrapper library, that project can be recorded, which is how a maintainer finds out about the code that will break when the client changes.
The Django relationship, and the migration story
pymemcache's place in the Python ecosystem comes through Django.
Since version 3.2, Django has included a pymemcache-based cache backend, and the README points at Django's own documentation for the settings. For older Django versions there is a separate package, django-pymemcache, maintained by somebody else.
That Django relationship is the main reason the library has survived with a slow release cadence. A caching library that a web framework has shipped as its default backend for years does not get abandoned in the way an independent utility might, and the maintainers are the people who work on the framework's caching path.
The README also links a migration guide titled Bye-bye python-memcached, hello pymemcache, which is a good indication that there is a substantial population of users arriving from the older client.
The credits list is long, around thirty names, which is what a mature utility with broad adoption looks like. The list includes contributors from Django itself and from a spread of companies, and it is topped by a note that Pinterest is hiring.
The repository also carries a CODE_OF_CONDUCT.md, a CONTRIBUTING.md, a ChangeLog.rst and a SECURITY.md. The security file is the one worth noticing for a library that sits in the request path of a web application, because a cache client that mishandles a malformed response can be a problem even though the data it holds is expendable.
How it compares to the other Python memcached clients
The README devotes a whole section to comparisons with three other libraries, and the reasoning is the most useful part of the document for anyone choosing between them.
pylibmc is a wrapper around libmemcached implemented in C. The README says it is fast, implements consistent hashing, the full memcached protocol and timeouts. Against it, pymemcache's advantages are the noreply flag, which pylibmc does not provide, and purity: pylibmc is not pure Python, so using it with libraries like gevent is out of the question, and its dependency on libmemcached poses challenges, because it must be built against the same version of libmemcached that it will use at runtime. That last point is the one that bites in production, where a build machine and a runtime image can drift apart.
python-memcached implements the entire memcached text protocol, has a single timeout for all socket calls and has a flexible approach to serialization. It is also entirely Python, so it works well with gevent. Its weaknesses, as listed: it is tied to using thread locals, does not implement noreply, cannot treat errors as cache misses, and is slower than both pylibmc and pymemcache. It is also tied to a specific method for handling clusters of memcached servers.
memcache_client comes from the team at Mixpanel. It has more fine-grained support for socket timeouts but only connects to a single host, does not support most of the memcached API, just get, set, delete and stats, does not support noreply, has no serialization or deserialization support, and cannot treat errors as cache misses. The README links Mixpanel's own blog post about why they wrote it, and the migration guide is the one referred to as Bye-bye python-memcached.
Read together, the comparisons describe a progression. pylibmc for raw speed, with a dependency bill. python-memcached for the older, slower, gevent-compatible option. memcache_client for a narrow feature set with fine-grained timeouts. And pymemcache for the combination that is complete, pure Python and treats failures as misses.
Limits: the noreply trade-off, error-as-miss, and the release gap
Several limits are worth being concrete about.
The first is the noreply trade-off. Skipping the acknowledgement makes writes faster because you do not wait for a reply, and it means the client cannot know that a write failed. A value that silently did not land is a value that will be missing from the cache later, and in a system where the cache is being used as a write-through buffer rather than as a read cache, that distinction matters a lot. The flag is optional and off by default, but it is the reason to reach for this client, so it is the thing to think about first.
The second is the error-as-miss option. Treating network and memcached errors as cache misses is the correct behaviour for a read-through cache in a request path, because a cache outage should degrade to a database read rather than to a 500. It is the wrong behaviour for anything that treats the cache as authoritative, and it can mask a misconfigured server indefinitely, because the application never fails and the cache is simply always empty.
The third is the release gap. The newest tag is v4.0.0 from October 2022 and the branch has been pushed to within the last week, so the fixes are in the repository and not necessarily in the version pip gives you. That is the normal state for a library where the framework ships it, and it is worth checking the ChangeLog.rst to see whether the changes are in a release.
The fourth is protocol coverage. This is a text protocol client, so it cannot talk to a memcached configured for the binary protocol, which some managed cache services default to. That is a deployment check rather than a library limitation, but it catches people.
The fifth is that pure Python has a ceiling. There is a C client that will do more operations per second on the same machine, and the README's own comparison says so. If your workload is dominated by cache misses rather than cache hits, the client is not your bottleneck and the difference does not matter.
This client against pylibmc and against talking to the protocol yourself
Two comparisons make the choice clearer.
The first is against pylibmc. The difference in approach is where the work happens. pylibmc does the protocol in C, so it is faster and it needs a native library compiled and version-matched to what it will use at runtime. pymemcache does the protocol in Python, so it installs anywhere Python runs, works under gevent because there is no C extension in the way, and can be read and modified by whoever owns the application.
That last property is not a small one for a client whose behaviour affects a web application's correctness. The noreply semantics, the error handling, the timeouts: you can read how pymemcache implements each of them, and Django's cache backend is built on it, so the behaviour is exercised by a very large body of production systems.
The second comparison is against speaking the text protocol yourself over a socket. It is not hard. The protocol is a handful of verbs, get, set, delete, and the value encoding is simple. What you give up is the parts that are easy to get subtly wrong: the noreply pipeline behaviour, the timeout distinction between connect and read, the error classification that lets you distinguish a network failure from a miss, and the serialisation layer that has to match what your application expects.
So the honest framing is that pymemcache earns its place when you want the semantics to be right and the deployment to be simple, and it is the wrong choice when throughput is the only thing that matters. Since the library is also the one Django ships, the probability that its behaviour is correct for your application is higher than for something you wrote yourself, and that is worth more than a speed difference on a workload that is probably I/O bound anyway.
Editorial conclusion
Adopt pymemcache when you want the memcached client to be pure Python, so it works under gevent and does not need libmemcached compiled against the right version. Do not choose it for the highest raw throughput on a stable platform, since a C wrapper will beat it. Verify first that your memcached deployment speaks the text protocol rather than the binary one, that your Python version is covered by the project's supported range, and that the error-as-miss behaviour is what you want, since it can hide a genuinely broken cache server.
Frequently asked questions
What features does pymemcache provide?
The README lists a complete implementation of the memcached text protocol, connections over UNIX sockets or TCP on IPv4 and IPv6, configurable timeouts for socket connect and for send and receive calls, access to the noreply flag which can significantly increase the speed of writes, a flexible and modular approach to serialization and deserialization, and the optional ability to treat network and memcached errors as cache misses.
How do I install pymemcache and run its tests?
Install with pip install pymemcache. For development, clone the repository, change into the pymemcache directory and run tox, making sure you have a local memcached server running, which the README calls out as a requirement.
How does pymemcache compare with pylibmc and python-memcached?
pylibmc wraps libmemcached in C and is fast with consistent hashing and timeouts, but it does not provide the noreply flag, is not pure Python so gevent is out of the question, and must be built against the same libmemcached version it will use at runtime. python-memcached implements the full text protocol in Python and works with gevent, but has a single timeout for all socket calls, is tied to thread locals, does not implement noreply, cannot treat errors as cache misses and is slower than both.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pinterest-pymemcache)Was this useful?