{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreicsonby2dxqumxz74asvfmnhlbympunexvjdn3ux5orars5yr3r2i",
"uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mlr7vh5ai4b2"
},
"path": "/t/ann-hpgsql-a-pure-haskell-postgresql-driver-no-libpq/14101#post_1",
"publishedAt": "2026-05-13T19:54:15.000Z",
"site": "https://discourse.haskell.org",
"tags": [
"hpgsql",
"Interruption safety",
"postgresql-query",
"hasql-interpolate",
"hpgsql-simple-compat",
"codd",
"the repository",
"Some initial benchmarks",
"GitHub - mzabani/hpgsql: A pure Haskell (no libpq) postgresql driver that draws inspiration from postgresql-simple, has streaming built into its core, speaks postgresql's binary protocol, has pipelining, interruption safety, and (reasonable) thread safety. · GitHub",
"hpgsql: Pure Haskell PostgreSQL driver (no libpq)"
],
"textContent": "It’s a pleasure to announce hpgsql, a PostgreSQL driver written in pure Haskell (no libpq), with an API largely inspired by the great postgresql-simple library, but featuring:\n\n * Usage of PostgreSQL’s binary protocol\n * Query arguments passed via the protocol instead of being escaped into the query string\n * Pipelining\n * Prepared statements\n * Ability to stream query results directly from the socket (not just with cursors)\n * Interruption safety, except for very specific (and documented) edge cases\n * Thread safety, unless specific (and documented) instructions say otherwise\n * A SQL quasiquoter like the one in postgresql-query and hasql-interpolate\n\n\n\nHere’s an example of a pipeline mixing streams, prepared and non prepared statements:\n\n\n f :: Int -> IO (Stream (Of Aeson.Value) IO ())\n f val = do\n (updateTbl :: IO (), aggRes :: IO (Only Int), largeResults) <-\n runPipeline conn $\n (,,)\n <$> pipelineExec_ [sql|UPDATE tbl SET val=#{val}|]\n <*> pipeline1 [sql|SELECT SUM(val) FROM tbl|]\n <*> pipelineSWith\n (rowDecoder @(Vector Int, Vector Text))\n -- We use a prepared statement for the query below\n [sqlPrep|SELECT x, y FROM tbl|]\n updateTbl\n Only total <- aggRes\n Streaming.map Aeson.toJSON <$> largeResults\n\n\nAlso, I am maintaining hpgsql-simple-compat, a fork of postgresql-simple that preserves its API as much as I could make it, but with internals rewritten to use hpgsql. The idea is to provide a simpler migration path from postgresql-simple; one that allows a smaller initial changeset and then the possibility of migrating queries to hpgsql one at a time. I have even migrated a CLI tool of mine, codd, as an example.\n\nhpgsql-simple-compat is not in Hackage as I wasn’t sure duplicating the search space with modules, types, and functions already in postgresql-simple would annoy users. It’s in the “hpgsql-simple-compat” folder in the repository.\n\nSome initial benchmarks show hpgsql can materialize rows from a query in ~38% the time postgresql-simple takes, and ~70% the time hasql takes (on my computer, Linux x64, GHC 9.10.3, compiled with -O1). Peak memory usage is trickier to analyze, and I therefore welcome people that know more to read the benchmarks page and help me better understand them. Also, please scrutinize these benchmarks as much as you can.\n\nI want to encourage and welcome contributions, bug reports, questions, suggestions. Nothing’s off the table: what would you want or what do you need from such a library?\n\nI really want to hear from the community, both those eager to switch and potential future users.\n\n * Link to the repository: GitHub - mzabani/hpgsql: A pure Haskell (no libpq) postgresql driver that draws inspiration from postgresql-simple, has streaming built into its core, speaks postgresql's binary protocol, has pipelining, interruption safety, and (reasonable) thread safety. · GitHub (contains both hpgsql and hpgsql-simple-compat)\n * Link to hackage: hpgsql: Pure Haskell PostgreSQL driver (no libpq)\n\n",
"title": "[ANN] hpgsql, a pure Haskell PostgreSQL driver (no libpq)"
}