# \[ANN\] Postgres.jl: a Julia-native PostgreSQL client

**URL:** <https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504>\
**Category:** Package Announcements\
**Created:** [September 16, 2026, 9:46pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504 "2026-09-16T21:46:22Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)\
**Post date:** [September 16, 2026, 9:46pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/1 "2026-09-16T21:46:23Z")

</div>

Hey all,

I’ve been working on [Postgres.jl](https://github.com/JuliaDatabases/Postgres.jl) for a while now, a PostgreSQL client written in Julia! [Version 2.0](https://github.com/JuliaDatabases/Postgres.jl/releases/tag/v2.0.0) is available, and I’d love to have people try it out.

Postgres.jl implements PostgreSQL’s wire protocol directly, using [Reseau.jl](https://github.com/JuliaServices/Reseau.jl) for networking. It doesn’t wrap libpq. The public API uses `DBInterface` for connections and queries, and query results support both `Tables.jl` and `StructUtils.jl`, so results can be handled in nice tabular or domain-model friendly ways, respectively.

Highlights include:

- **Parameterized queries and prepared statements.** Bind Julia values through `DBInterface.execute`, with connection-level statement caching.
- **Transactions and connection pools.** Transaction blocks handle commit and rollback, nested transactions use savepoints, and pools give concurrent tasks separate connections.
- **Streaming and bulk transfer.** Cursors fetch rows in batches. PostgreSQL’s `COPY` protocol supports bulk input and output, including binary payloads.
- **Typed results.** Read rows through `Tables.jl`, or ask for a Julia struct or named tuple through the StructUtils integration. Custom enums, composites, and ranges can be registered for decoding.
- **Shared timestamp and decimal types.** Timestamps use `Durations.Timestamp{Dates.Microsecond}`, preserving PostgreSQL’s six fractional digits. Numeric values use `DataDecimals.DecimalValue{DataDecimals.Int256}`, preserving the value and scale. Explicit decimal targets require an exact conversion.
- **PostgreSQL connection features.** URI and keyword connection strings, environment defaults, SCRAM authentication, TLS, query cancellation, and `LISTEN`/`NOTIFY`.

## A small example

On Julia 1.10 or later:

```julia
import Pkg
Pkg.add("Postgres)

```

With a local PostgreSQL server, adjust the connection details and run:

```julia
using Postgres

params = Postgres.ConnectionParams(
    host="127.0.0.1", port=5432,
    user="postgres", password="postgres", dbname="postgres",
    sslmode="disable", # local example; use verify-full for authenticated TLS
)

DBInterface.connect(Postgres.Connection, params) do conn
    row = only(DBInterface.execute(conn, raw"""
        SELECT $1::int AS id,
               $2::text AS name,
               '2026-09-16 12:34:56.123456'::timestamp AS observed_at,
               12.3400::numeric AS amount
        """, (1, "Julia")))

    @show row.id row.name
    @show row.observed_at # all six fractional digits
    @show row.amount # 12.3400
end

```

`using Postgres` re-exports `DBInterface`; package-specific APIs use the `Postgres.` namespace. The [manual](https://juliadatabases.org/Postgres.jl/stable/manual/) has examples for transactions, pools, typed queries, cursors, and `COPY`.

## A few details worth knowing

`timestamptz` results are returned in UTC. Explicit `DateTime` fields are available when millisecond precision is sufficient; those fields truncate finer fractions. Timestamp parameters with submicrosecond precision raise an error.

CI tests PostgreSQL 14 through 18, including real database round trips and certificate tests on Linux. The suite also includes seeded fuzz tests for protocol framing, connection strings, arrays, and composite values. Connections currently use TCP; Unix-domain sockets are not supported. Client-certificate TLS uses TLS 1.2. The [support policy](https://juliadatabases.org/Postgres.jl/stable/support/) covers the other limits, including transaction-mode poolers.

Please give it a try! I’d especially appreciate reports from real applications, managed PostgreSQL services, and PgBouncer setups. If something doesn’t work, [open an issue](https://github.com/JuliaDatabases/Postgres.jl/issues) with the Julia/Postgres.jl/PostgreSQL versions and a small example, with credentials removed. Questions and suggestions here are welcome too.

-Jacob Quinn

---

<div class="post-metadata">

**Author:** ![danvinci](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danvinci/32/21445_2.png) [@danvinci](https://discourse.julialang.org/u/danvinci)\
**Post date:** [September 17, 2026, 9:22am UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/2 "2026-09-17T09:22:57Z")

</div>

Starred!

really appreciate you, so many best-in-class foundational packages (HTTP, CSV, JSON), and now this! if we only had x10 Quinnj the Julia lang and ecosystem would fly

---

<div class="post-metadata">

**Author:** ![csvance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/csvance/32/218927_2.png) [@csvance](https://discourse.julialang.org/u/csvance)\
**Post date:** [September 17, 2026, 1:23pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/3 "2026-09-17T13:23:43Z")

</div>

> [@danvinci](#):
>
> really appreciate you, so many best-in-class foundational packages (HTTP, CSV, JSON), and now this! if we only had x10 Quinnj the Julia lang and ecosystem would fly

Agreed! Only a year ago I was worried if investing in Julia would be a mistake for production systems, especially for smaller teams that cannot afford to write high quality foundational packages themselves. That concern was entirely erased in 2026. Big thank you to Jacob and everyone else involved in these efforts, it’s significantly expanded the horizons for Julia in terms of what is possible and painless in the language now.

Having a modern / native Postgres client is already making me consider Julia for future database applications, can’t wait to try it out!

---

<div class="post-metadata">

**Author:** ![Roger\_Powell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roger_powell/32/21586_2.png) [@Roger\_Powell](https://discourse.julialang.org/u/Roger_Powell)\
**Post date:** [September 19, 2026, 9:42pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/4 "2026-09-19T21:42:14Z")

</div>

I have been using [LibPQ.jl](https://juliadatabases.org/LibPQ.jl/dev/) for several years and found it both performant and easy to use. Could you briefly comment on what the advantage of `Postgresql.jl` is over `LibPQ.jl`? Should I switch?

Many thanks.

---

<div class="post-metadata">

**Author:** ![wookyoung](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wookyoung/32/157_2.png) [@wookyoung](https://discourse.julialang.org/u/wookyoung)\
**Post date:** [September 20, 2026, 12:08pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/5 "2026-09-20T12:08:00Z")

</div>

This is excellent work. there’s [Octo.jl](https://github.com/wookay/Octo.jl) v0.3.0 release. it’s about using Postgres.jl as its backend. Thanks to this, the update process was smooth and easy.

---

<div class="post-metadata">

**Author:** ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)\
**Post date:** [September 21, 2026, 5:26pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/6 "2026-09-21T17:26:18Z")

</div>

Thanks, Roger, the main reasons to consider switching are the additional conveniences and Julia integration, I asked AI to help come up with a few useful bullet points highlighting the differences:

- **Less connection and transaction code.** Postgres.jl includes connection pools, transaction blocks that handle commit/rollback, nested transactions through savepoints, and cursors that fetch results in batches. You can build these workflows with LibPQ, but Postgres provides the helpers directly.

- **Query directly into your own types.** The StructUtils integration lets a query return a Julia struct or `Vector{YourType}`, including mapping SQL column names to Julia field names. This can remove a fair amount of result-conversion code. These features have examples in the [manual](https://github.com/JuliaDatabases/Postgres.jl/blob/v2.0.0/docs/src/manual.md).

- **Microsecond timestamps by default.** Postgres preserves PostgreSQL’s six fractional timestamp digits. LibPQ’s default timestamp mappings retain milliseconds, although it supports custom conversions. This is a concrete benefit if timestamp precision matters to your application. ([Postgres types](https://github.com/JuliaDatabases/Postgres.jl/blob/v2.0.0/docs/src/support.md#types), [LibPQ timestamp parsing](https://github.com/JuliaDatabases/LibPQ.jl/blob/master/src/parsing.jl#L234-L286))

- **The client implementation is Julia.** Postgres implements the wire protocol directly, without depending on libpq. That makes the driver easier to inspect and extend using Julia tools. It does not, by itself, mean every query will be faster.

In addition, I think Postgres.jl is currently in a more maintainable state; LibPQ.jl has long lacked active maintainership and it’s been hard to get updates merged & released.

Give it a whirl and let me know how it goes!

---

<div class="post-metadata">

**Author:** ![Roger\_Powell](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roger_powell/32/21586_2.png) [@Roger\_Powell](https://discourse.julialang.org/u/Roger_Powell)\
**Post date:** [September 21, 2026, 8:05pm UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/7 "2026-09-21T20:05:27Z")

</div>

Thanks! Sounds good, but I have a lot of code that uses LibPQ.jl. Nevertheless, I will give it a try, I have to do a lot of boxing into Julia types and that sounds easier or even unnecessary with Postgres.jl

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [September 30, 2026, 1:54am UTC](https://discourse.julialang.org/t/ann-postgres-jl-a-julia-native-postgresql-client/139504/8 "2026-09-30T01:54:05Z")

</div>

I switched from LibPQ.jl to Postres.jl with the benefit that my program will now precompile as mentioned in [Interface FunSQL with LibPQ using DBInterface - #11 by Jake](https://discourse.julialang.org/t/interface-funsql-with-libpq-using-dbinterface/99635/11) . For details on the interface see [Using FunSQL.jl with Postgres.jl](https://discourse.julialang.org/t/using-funsql-jl-with-postgres-jl/139564) .
