memcache
A memcached client library.
https://github.com/dterei/memcache-hs#readme
| LTS Haskell 24.64: | 0.3.0.2 |
| Stackage Nightly 2026-10-20: | 0.4.2.0 |
| Latest on Hackage: | 0.4.2.0 |
memcache-0.4.2.0@sha256:1aa271847ea66ab931d625fb067f1366cc22c03dc10c15e5c7caa4eaa4e62d9e,4574Module documentation for 0.4.2.0
memcache: Haskell Memcached Client
A client library for a memcached cluster.
It supports the Meta Text memcached protocol and username/password authentication. Keys containing whitespace or control bytes are sent using its base64 binary-key mode. The encoded key must still fit within 250 bytes. It supports connecting to a single, or a cluster of memcached servers. When connecting to a cluster, consistent hashing is used for routing requests to the appropriate server.
This library requires memcached 1.6.0 or newer, the first release with the
meta commands. Against older servers every operation is rejected with ERROR.
Authentication uses a memcached auth file with -Y authfile, an experimental
ASCII-protocol auth mode added in memcached 1.5.15; the old binary protocol
-S SASL mode is not supported. Enabling -Y also disables binary and UDP
protocols on the server. getMany uses quiet misses, so a server connection
failure can be indistinguishable from a cache miss.
The client operations, including getMany, use direct Meta Text encoders and
the Response type; the former request and response wrapper types are no longer
provided.
Usage
Add memcache to your package’s build-depends. Everything most programs need
is exported from Database.Memcache.Client:
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import qualified Database.Memcache.Client as M
main :: IO ()
main = do
-- Connect to memcached on 127.0.0.1:11211 with the default options.
mc <- M.newClient [M.def] M.def
-- Store a value with flags 0 that never expires, then read it back along
-- with its flags and CAS version.
_ <- M.set mc "greeting" "hello" 0 0
hit <- M.get mc "greeting"
case hit of
Nothing -> putStrLn "miss"
Just (value, _flags, version) -> do
print value
-- Only overwrite the value if it hasn't changed since we read it.
updated <- M.cas mc "greeting" "hello again" 0 0 version
putStrLn (maybe "changed by someone else" (const "updated") updated)
-- Create the counter as 1 if it is missing, otherwise add 1 to it.
visits <- M.increment mc "visits" 1 1 0 0
print (fst <$> visits)
M.quit mc
Keys and values are strict ByteStrings. Misses are returned as Nothing,
while unexpected failures are thrown as a MemcacheError or a network
IOException. Operations that take a CAS Version skip the check when it is
0. increment and decrement create a missing key with the given initial
value, unless the expiration is maxBound. The
Database.Memcache.Client
documentation covers every operation, along with the timeouts, retries and
failover configured through Options.
Servers and authentication
newClient takes one ServerSpec per server, and routes each key to one of
them. Credentials are set per server:
mc <- M.newClient
[ M.ServerSpec "cache1.internal" "11211" (M.Auth "user" "secret")
, M.ServerSpec "cache2.internal" "11211" (M.Auth "user" "secret")
]
M.def
parseServerSpec, from Database.Memcache.Types, reads a server from a
memcached://[user:password@]host[:port] URI instead. The host defaults to
127.0.0.1 and the port to 11211:
import Database.Memcache.Types (parseServerSpec)
spec <- either fail pure (parseServerSpec "memcached://user:[email protected]:11211")
mc <- M.newClient [spec] M.def
The server must be started with -Y <authfile>, where the auth file holds one
username:password line per user. This library connects without TLS, so
credentials and all data are sent unencrypted; only rely on them within a
trusted network.
Amazon ElastiCache
Database.Memcache.ElastiCacheClient creates a client from an ElastiCache
configuration endpoint (the address containing .cfg). It discovers the
cluster’s nodes, then refreshes the node list in a background thread on the
given interval, in microseconds as for threadDelay:
import qualified Database.Memcache.ElastiCacheClient as EC
endpoint <- either fail pure $
EC.parseConfigurationEndpoint "memcached://mycluster.abc123.cfg.use1.cache.amazonaws.com:11211"
mc <- EC.newClient M.def (60 * 1000000) endpoint
Licensing
This library is BSD-licensed.
Tools
This library also includes a few tools for manipulating and experimenting with memcached servers.
OpGen– A load generator for memcached. Doesn’t collect timing statistics, other tools like mutilate already do that very well. This tool is useful in conjunction with mutilate.Loader– A tool to load random data of a certain size into a memcached server. Useful for priming a server for testing.
Architecture Notes
We’re relying on Data.Pool for thread safety right now. Each server has its
own pool, and grabbing a connection from it (withResource) blocks other
requests using that connection until the operation completes. getMany is the
exception: it pipelines quiet Meta Text requests over one pooled connection.
By default each server’s pool holds a single connection (soNumResources = 1),
so concurrent operations against the same server wait for each other. Raising
soNumResources in the ServerOptions set through optsServerOptions allows
concurrent operations without requiring a separate pool implementation.
Either way, a pool is fine for now.
Other clients
Get involved!
We are happy to receive bug reports, fixes, documentation enhancements, and other improvements.
Please report bugs via the github issue tracker, and security issues as described in the security policy.
Master git repository:
git clone https://github.com/dterei/memcache-hs.git
Development
The package builds with Stack or cabal, on GHC 9.2 or newer:
stack build
stack test
cabal build
cabal test all
stack.yaml uses Stackage LTS 22.14 (GHC 9.6). The oldest and newest snapshots
CI tests against have their own files, for example
stack --stack-yaml stack-lts-20.26.yaml test for GHC 9.2.
There are two test suites:
specholds the unit and property tests, which run against an in-process mock server and need nothing installed.integrationstarts its ownmemcachedservers on free local ports and tests against them, so it needs memcached 1.6 or newer on yourPATH. Without it, the suite reports a single pending test instead of failing. memcached refuses to run as root without-u, so run the suite as an ordinary user.
CI lints with HLint 3.10, so please
check that hlint . prints No hints before opening a pull request. For any
user-visible change, add a line to CHANGELOG.md under an
Unreleased heading at the top, adding the heading if it isn’t there.
CI runs both build tools on every pull request. The CI workflow builds and
tests with Stack against each stack*.yaml snapshot, and runs HLint and
weeder. The Cabal workflow builds and tests with cabal on GHC 9.2 to 9.14,
builds the library against the oldest dependency versions its bounds allow,
and builds and tests the source distribution; it also runs every Monday, so a
new dependency release that breaks the build shows up without a push. Both
install memcached, so the integration suite runs in full.
Authors
This library is written and maintained by David Terei ([email protected]).
Contributions have been made by the following great people:
- Alfredo Di Napoli ([email protected])
- Amit Levy
- Chris Martin
- drlkf
- Joel McCracken
- Steven Leiva
Changes
0.4.2.0 - October 20th, 2026
No API changes from 0.4.0.0. This is the first Hackage release since 0.4.0.0, so it also includes the 0.4.1.0 changes below.
- Fix
getManyreturning one key’s value under another key’s name when a plain key equals the other’s base64 form, such as"IA=="and" ". - Requests that carry a value or a number are now encoded into a single
buffer instead of a chain of appends that copied the value once per piece.
Encoding a 64KiB
settakes about 4µs instead of about 57µs. - Document that a
Versionof0skips the CAS check, whatcas,replace,append,prependanddeletedo for a missing key or a version mismatch, and whenincrementanddecrementcreate a missing key. Add the missingOverloadedStringsto the usage examples inDatabase.Memcache.Clientand the package description, add usage and development instructions to the README, and replace the templateSECURITY.mdwith a full security policy.
0.4.1.0 - October 19th, 2026
Not uploaded to Hackage; these changes first ship there in 0.4.2.0. No API or behaviour changes from 0.4.0.0.
- Reading a large value no longer allocates memory quadratic in its size. Each receive is now capped at 64KiB, so fetching a 32MiB value allocates about 67MB rather than about 1.7GB.
- Drop the dependency on
errors(and, through it,safeandtransformers-compat), which was only used for a one-line helper. - Replace the hpack
package.yamlwith a hand-writtenmemcache.cabal(cabal-version: 3.0) that lists the exposed modules explicitly and gives each component only the dependencies it uses. RemoveSetup.hs, which only did whatbuild-type: Simpledoes anyway. The license field is now the SPDX identifierBSD-3-Clause; the license itself is unchanged. - Declare support for GHC 9.2 to 9.14 in
tested-with. - Fix the
parserbenchmark, which no longer compiled, and extend it to cover key encoding, more requests, and reading CAS, flags and numbers out of responses. - Expand the package description. Hackage already shows it, as a revision of 0.4.0.0.
- Document the
InvalidAuthenticationandKeyTooLongconstructors ofClientError, and fix typos in the Haddock documentation. - Greatly expand the test suite. Unit tests against mock servers now cover
every request encoder and client operation, retries and failover,
authentication,
parseServerSpecand ElastiCache discovery, and the integration tests also run against memcached in-Yauth-file mode and against a three-server cluster. - CI builds and tests with cabal on GHC 9.2 to 9.14 and from the source distribution, builds the library against the oldest dependency versions the bounds allow, and runs weekly, as well as building with Stack and running HLint and weeder.
0.4.0.0 - October 19th, 2026
- Replace the deprecated binary protocol with buffered Meta Text requests.
- Add base64 binary-key support,
getMany, hspec tests, andAuth. - Remove binary protocol and builder dependencies.
- Replace request/response wrapper types with direct Meta Text encoders and
Response. - Authentication now uses the server’s experimental
-Y authfilemode (introduced in memcached 1.5.15) instead of binary-SSASL. encodeKeynow returns a validatedWireKey; request builders and the low-levelkeyedOpAPIs accept encoded keys to avoid partial validation and repeated encoding.- Requires memcached 1.6.0 or newer for the meta commands.
statsreturns[(Server, StatResults)]rather than[(Server, Maybe StatResults)]; theNothingcase was unreachable. Stat values containing spaces are no longer truncated, and stats arguments may now contain spaces (stats cachedump 1 100).StatuslosesErrInvalidArgsandErrUnknownCommand, which have no Meta Text equivalent and now surface asProtocolError.ErrValueTooLarge,ErrOutOfMemoryandErrValueNonNumericare recovered from the server’s error text so they keep being reported asOpError.- A command the server rejects (
ERROR,CLIENT_ERROR) or answers with an operation status is no longer retried, and no longer counts towards marking a server dead. getManywrites each batch in a single bounded send, so a large key list cannot deadlock against the server’s replies.- Response lines are capped at 8KiB, bounding memory use on a desynchronised connection.
- Authentication first checks that the server is in auth-file mode and
refuses to send credentials otherwise, so they are never stored as a plain
authitem. Credentials with a forbidden delimiter, or a server that isn’t in auth-file mode, raiseClientError InvalidAuthentication, and credentials the server rejects raiseOpError TextAuthFail. Neither is retried or marks the server dead. - Empty keys, and keys longer than 250 bytes, are rejected with
ClientError KeyTooLongbefore anything is sent. appendandprependon a missing key returnNothinginstead of throwingOpError ErrItemNotStored.statsaccepts replies made of lines other thanSTAT, such as those fromstats resetandstats cachedump.Database.Memcache.Socketsends and receives on a bufferedConnectionwithsendRawandrecvResponse, replacingsendandrecv.- ElastiCache auto discovery no longer holds the server list lock while waiting for the next refresh.
- Exception helpers now come from
unliftio, which is a new dependency. - Library dependencies declare lower bounds, set to the oldest versions CI builds against (GHC 9.2, Stackage LTS 20.26).
- Depend on
data-defaultinstead of the deprecateddata-default-class, which is now a compatibility shim overdata-default0.8. - Add
Database.Memcache.ElastiCacheClient, which creates a client from an Amazon ElastiCache configuration endpoint and refreshes its node list on an interval. - Add
parseServerSpec, which reads aServerSpecfrom amemcached://URI. OptionsgainsoptsServerOptions, whoseServerOptionsset the size, stripes and keep-alive of each server’s connection pool, andoptsServerSpecsToServers, which controls how servers are created.Database.Memcache.ServerexportsnewServerDefaultin place ofnewServer.
0.3.0.2 - March 27th, 2024
- Make the key hashing algorithm configurable by clients – that is, let clients provide a function mapping a key to a server.
0.3.0.1 - January 17th, 2021
- No changes, needed a new release to fix a Hackage upload issue.
0.3.0.0 - January 17th, 2021
- Bump package dependencies for newer GHC/back/network.
- Update code to work with newer dependencies.
0.2.0.1 - November 2nd, 2016
- Fix compatibility with latest
data-default-class - Add new ReqRaw type for external clients to implement custom requests. Quite a hack right now, so behind a WARNING pragma.
0.2.0.0 - May 27th, 2016
- Big design change to reduce code duplication (
Protocolmodule gone). - Remove
Optionstype - just fixed configuration for now. - Design change also allows proper retry handling on operation failure - we retry an operation against the same server, but after N consecutive failures, we mark the server as dead and don’t try using it again until M seconds has passed.
- Simplify exception hierarchy - just one type
MemcacheErrornow for exceptions. - Remove
defaultOptionsanddefaultServerSpec, will revisit usefulness. - Remove many
Typeableinstances. - Support better testing with a mock Memcached server.
- Fix bug in socket handling - detected EOF properly.
- Greatly improve documentation.
- Use
data-default-classfor defaults of servers and options.
0.1.0.1 - February 26th, 2016
- Consistent usage of ‘memcached’ instead of ‘memcache’.
- Document
Database.Memcache.Client. - Add inline pragmas in appropriate places.
- Fix bug handling fragmented IP packets (Alfredo Di Napoli).
0.1.0.0 - May 18th, 2015
- First proper release (although still lots of rough edges!).
- Filled out
Data.Memcache.Clientto a complete API. - Integrated cluster and authentication handling.
- Better error and exception handling.
- Fix compilation under GHC 7.10.
0.0.1 - May 5th, 2015
- Initial (incomplete) support for a cluster of memcached servers.
- Fixed compilation under GHC 7.4.
0.0.0 - August 23rd, 2013
- Initial release. Support for a single server.