# Hasql v2: the Native Era

**URL:** <https://discourse.haskell.org/t/hasql-v2-the-native-era/14553>\
**Category:** Announcements\
**Created:** [August 13, 2026, 2:13pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553 "2026-08-13T14:13:06Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![nikita-volkov](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/nikita-volkov/32/3387_2.png) [@nikita-volkov](https://discourse.haskell.org/u/nikita-volkov)\
**Post date:** [August 13, 2026, 2:13pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553/1 "2026-08-13T14:13:06Z")

</div>

Hasql v2 is out. It can now run natively in Haskell with no external dependencies, or the same way it always has, using “libpq”. It’s the user’s choice now. No performance degradation and minimal changes to the API.

I’ve written up the post explaining the reasoning and how it was achieved:

> **[Hasql v2: the Native Era](https://nikita-volkov.github.io/hasql-v2-the-native-era/)**
>
> Hasql v2 is here! It can run natively in Haskell with no external dependencies or the same way it always has, using “libpq”. It’s the user’s choice now. No breaking changes in the API except for the choice of the adapter in the connection settings.

---

<div class="post-metadata">

**Author:** ![brandonchinn178](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/brandonchinn178/32/5103_2.png) [@brandonchinn178](https://discourse.haskell.org/u/brandonchinn178)\
**Post date:** [August 16, 2026, 12:48pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553/2 "2026-08-16T12:48:45Z")

</div>

What’s the difference between pqi and hpgsql? cc @mzabani

---

<div class="post-metadata">

**Author:** ![mzabani](https://avatars.discourse-cdn.com/v4/letter/m/c68b51/32.png) [@mzabani](https://discourse.haskell.org/u/mzabani)\
**Post date:** [August 16, 2026, 2:25pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553/3 "2026-08-16T14:25:56Z")

</div>

AFAICT (and quoting the docs a bit) `pqi` reproduces the API surface of the `postgresql-libpq` package without any ties to libpq or any particular implementation of that API itself.

[`hpgsql`](https://hackage.haskell.org/package/hpgsql) provides a much higher-level API than anything trying to replace postgresql-libpq - it’s more of a cousin to `postgresql-simple` and `hasql`.

hpgsql has its own internal and lower-level APIs, of course, that I evolved while developing hpgsql to have the things I wanted, including for example interruption safety, thread safety and streams. [They are very different from postgresql-libpq’s](https://github.com/mzabani/hpgsql/blob/c9c8c7700f8ac4a97906919fc96889e953ce26d8/hpgsql/src/Hpgsql/Internal.hs#L855-L859), and I honest don’t know how easily it could be retrofitted to a libpq-style API, though I think it should be possible (maybe with minor tradeoffs).

My (biased and actually not that well informed about libpq) opinion, however, has been that the PostgreSQL ecosystem in Haskell would benefit from moving away from libpq-style APIs. We have wonderful abstractions and luxuries - from Streams to interruption safety and just plain pure code -, and though I didn’t look too deeply, while I was developing hpgsql it felt like not having the libpq-style APIs forced on me gave me a lot of freedom to achieve those goals, not to mention a lot of performance work (and there’s still a lot more of that coming!).

I of course understand that asking other library authors to reimplement their libraries is a huge effort and risk, and that there’s a long way towards native postgres implementations to support all the auth methods and TLS encryption, so I applaud Nikita’s effort to make a call towards a common interface. And if I ever expose one from hpgsql, I’ll make sure to adapt it to `pqi`.

---

<div class="post-metadata">

**Author:** ![viktor](https://avatars.discourse-cdn.com/v4/letter/v/d6d6ee/32.png) [@viktor](https://discourse.haskell.org/u/viktor)\
**Post date:** [August 17, 2026, 12:38pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553/4 "2026-08-17T12:38:51Z")

</div>

FWIW, I successfully built my DNSSEC/DANE survey engine with each of `pqi-ffi` and `pqi-native`. For the latter I had to add support for unix-domain socket connections (as noted in the issue and pull request).

Once both were built, though “native” produces correct results I quickly found that performance of “native” is 3–6x slower when processing a bulk report fetching 10k rows at a time from a cursor for a total of around 20M rows.

The inner loop uses `Hasql.Decoders.rowVector` to decode and process the rows returned by each fetch. This is perhaps expected given the initial focus on correctness.

---

<div class="post-metadata">

**Author:** ![nikita-volkov](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/nikita-volkov/32/3387_2.png) [@nikita-volkov](https://discourse.haskell.org/u/nikita-volkov)\
**Post date:** [August 17, 2026, 5:07pm UTC](https://discourse.haskell.org/t/hasql-v2-the-native-era/14553/5 "2026-08-17T17:07:08Z")

</div>

I’ve uncovered a usecase of `pqi` that I did not intend. It’s trivial to implement all sorts of proxies between `hasql` and the underlying transport implementation (`pqi-native`, `pqi-ffi`).

One use case that it opened for me is testing edge cases of `hasql` against a mock `pqi` adapter.

But now I can imagine people implementing diagnostics and observability proxies that are specialized to `pqi` and thus are compatible not just with `hasql`, but any lib that integrates with `pqi` in the future.

Think `wai` for `postgres`.
