Skip to content
Go back

Understanding PostgreSQL Connection URIs

· Updated:
By SumGuy 5 min read
Understanding PostgreSQL Connection URIs

PostgreSQL, the powerful open-source relational database management system, uses a specific format called a connection URI (Uniform Resource Identifier) to provide a standardized way of establishing connections. These URIs streamline setup and offer flexible configuration options.

Understanding the Fundamentals

Let’s dissect the anatomy of a standard PostgreSQL connection URI:

postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]

Illustrative Examples

Common Connection Parameters

Tips and Tricks

Mastering PostgreSQL connection URIs gives you powerful control when establishing database connections. Using them effectively will streamline your database interactions and give you the flexibility to adjust connection properties as your application’s needs evolve.

The Gotchas That’ll Ruin Your Deploy Night

Theory’s great. But let’s talk about what actually breaks at 11 PM when your app can’t connect and you’re staring at a stack trace that just says connection refused.

Special Characters in Passwords Will Bite You

This one’s bitten more people than I can count. Your DBA sets a password like p@$$w0rd! and now your URI is silently broken because @ is the delimiter between credentials and host. The parser sees p as the username, $$w0rd! as the password fragment, and p as… who knows.

The fix is percent-encoding, but you need to do it properly — not just for spaces. Here’s a quick cheat sheet of characters that must be encoded:

CharacterEncoded
@%40
:%3A
/%2F
?%3F
#%23
%%25

You can encode it on the fly in bash without installing anything:

Terminal window
python3 -c "import urllib.parse; print(urllib.parse.quote(‘p@\$\$w0rd!’, safe=’’))"
# Output: p%40%24%24w0rd%21

Then your URI looks like: postgresql://user:p%40%24%24w0rd%21@localhost/mydb

SSL Mode: The Silent Killer

The default sslmode is prefer — Postgres will try SSL but fall back to plaintext if the server doesn’t support it. That sounds reasonable until you’re running in a production environment that requires SSL and your staging app worked fine without it, so you never noticed.

The modes you actually need to understand:

Terminal window
# Good for production with a managed DB (RDS, Supabase, Neon, etc.)
postgresql://user:[email protected]/mydb?sslmode=verify-full
# Good for local Docker Compose dev where there’s no SSL at all
postgresql://user:pass@localhost/mydb?sslmode=disable

If you get FATAL: SSL connection is required from a managed database and your connection string has no sslmode, that’s your problem. Add ?sslmode=require at minimum.

Unix Socket Connections Look Weird

When Postgres is running locally and you’re connecting as the postgres OS user, you’re probably using a Unix socket without realizing it. The URI form looks nothing like what you’d expect:

Terminal window
# Connect via Unix socket (the /var/run/postgresql directory contains the socket file)
postgresql:///mydb
# With an explicit socket path
postgresql://%2Fvar%2Frun%2Fpostgresql/mydb

Notice the host is empty or the socket path is percent-encoded in the netloc slot. This is why psql -U postgres mydb works on your server but psql postgresql://postgres@localhost/mydb fails — localhost forces a TCP connection, which then hits pg_hba.conf and authentication fails differently than the socket path.

Test Your URI Before It Fails in Production

Don’t wait for your app to blow up. psql accepts the full URI directly:

Terminal window
psql "postgresql://user:[email protected]:5432/mydb?sslmode=require"

If that connects, your app will too. If it doesn’t, you know it’s a URI/network/auth problem — not your application code. Saves you from the classic “is it my ORM or is it Postgres” debugging spiral where you waste 45 minutes reading SQLAlchemy docs when the issue was a typo in your .env file.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it'll show up above once verified.


Previous Post
Understanding Docker vs. Full Virtual Machines (VMs)
Next Post
Understanding printf vs echo in Bash

Discussion

Powered by Garrul . Sign in with GitHub or Google, or post anonymously.

Related Posts