DBW.

Intermediate

Encryption in Transit: TLS for Database Connections

Article diagram
July 22, 2026·10 min read

Production database connections require TLS with full certificate verification (`verify-full`) to protect against both passive eavesdropping and active man-in-the-middle attacks.

Introduction

Database connections carry some of the most sensitive data in any system: credentials, personally identifiable information, financial records, and application secrets.
Without encryption in transit, this data traverses the network as plaintext, vulnerable to passive eavesdropping, man-in-the-middle (MITM) attacks, and packet injection.
Transport Layer Security (TLS) is the standard protocol for protecting these connections.

Despite its importance, TLS for database connections is frequently misconfigured, partially deployed, or silently downgraded.
Understanding the mechanics of TLS at the database layer, including handshake behavior, certificate verification, cipher suite selection, and performance implications, is essential for engineers who operate production database infrastructure.

TLS Fundamentals in the Database Context

TLS operates between the transport layer (TCP) and the application layer.
For databases, this means TLS wraps the database wire protocol (e.g., PostgreSQL's frontend/backend protocol, MySQL's client/server protocol, or MongoDB's wire protocol) in an encrypted channel.
The database client and server negotiate a TLS session before any application-level authentication or query traffic is exchanged.

The security guarantees TLS provides are:

  • Confidentiality: Symmetric encryption (typically AES-128-GCM or AES-256-GCM) prevents eavesdropping on query content and results.
  • Integrity: HMAC or AEAD constructions detect any tampering with in-flight data.
  • Authentication: X.509 certificates allow the client to verify the server's identity, and optionally allow the server to verify the client's identity (mutual TLS, or mTLS).

A critical distinction exists between encrypting the connection and authenticating the peer.
Many database drivers default to encrypting traffic without verifying the server's certificate, which protects against passive sniffing but not against active MITM attacks.
This is a common and dangerous misconfiguration.

Walkthrough

TLS 1.3 Handshake for a Database Connection

diagram-1
TLS 1.3 handshake sequence for a database connection

The following walkthrough describes a TLS 1.3 handshake as it applies to a typical database connection.
TLS 1.3 (RFC 8446) reduces the handshake to one round trip in the common case compared to two round trips in TLS 1.2.

Step 1: TCP Connection Established The client opens a TCP connection to the database server on the appropriate port (e.g., 5432 for PostgreSQL, 3306 for MySQL).

Step 2: TLS Negotiation Signal Some databases use a protocol-level signal to initiate TLS.
PostgreSQL, for example, sends an SSLRequest message.
If the server supports TLS, it responds with a single byte S; otherwise it responds with N.
MySQL signals TLS capability via a flag in the initial handshake packet.
This pre-TLS negotiation happens in plaintext.

Step 3: ClientHello The client sends a ClientHello message containing:

  • Supported TLS versions (in TLS 1.3, this is communicated via the supported_versions extension)
  • A list of supported cipher suites (e.g., TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256)
  • Key shares for one or more key exchange groups (typically X25519 or P-256), sent speculatively to enable 1-RTT completion
  • SNI (Server Name Indication), if applicable

Step 4: ServerHello + Encrypted Extensions + Certificate + CertificateVerify + Finished In TLS 1.3, the server responds with all of these in a single flight:

  • ServerHello: selects cipher suite and key share
  • The server and client both derive handshake keys from the ECDHE shared secret
  • EncryptedExtensions: additional parameters, now encrypted. If the server requires client authentication, a CertificateRequest message is also included in this encrypted flight.
  • Certificate: the server's X.509 certificate chain
  • CertificateVerify: a signature over the handshake transcript, proving possession of the private key
  • Finished: a MAC over the entire handshake transcript

Step 5: Client Verification The client validates the server certificate against its trusted CA store, checks the hostname or IP against the certificate's Subject Alternative Name (SAN) entries, verifies the signature in CertificateVerify, and checks the Finished message.

Step 6: Client Finished The client sends its own Finished message.
Both sides derive application traffic keys.

Step 7 (Optional, mTLS): Client Certificate If the server requested client authentication (via CertificateRequest in Step 4), the client sends its own Certificate and CertificateVerify messages before Finished.

Step 8: Application Data The database wire protocol proceeds over the encrypted channel.
All subsequent traffic, including authentication credentials, queries, and result sets, is encrypted with the negotiated symmetric cipher.

Client                                          Server
  |                                                |
  |--- TCP SYN/SYN-ACK/ACK ---------------------->|
  |--- SSLRequest (PostgreSQL-specific) ---------->|
  |<-- 'S' (TLS accepted) ------------------------|
  |--- ClientHello (versions, ciphers, keyshare) ->|
  |<-- ServerHello, {EncryptedExtensions,          |
  |     Certificate, CertificateVerify, Finished} -|
  |--- {Finished} -------------------------------->|
  |<== Application data (encrypted) ==============>|

Certificate Verification Modes

diagram-2
TLS verification modes and their authentication properties

Database drivers typically expose several TLS verification modes.
The naming varies across systems, but the semantics cluster into a few categories:

ModeEncrypts?Verifies CA Chain?Verifies Hostname?MITM Protection?
disable / offNoNoNoNone
allow / preferMaybeNoNoNone
requireYesNoNoPassive only
verify-caYesYesNoPartial
verify-fullYesYesYesFull

The require mode is deceptively named.
It requires encryption but does not verify who is on the other end.
An attacker who can intercept TCP traffic can present any certificate, and the client will accept it.

verify-ca provides partial protection: it ensures the server certificate is signed by a trusted CA, but because it does not check the hostname, an attacker in possession of any certificate issued by that same trusted CA — for any hostname — can successfully impersonate the database server.
Only verify-full closes this gap by additionally validating that the certificate's Subject Alternative Name matches the server hostname or IP.

PostgreSQL's libpq defaults to prefer, which attempts TLS when the server supports it, but does not verify certificates, providing no protection against MITM attacks.
MySQL's Connector/J defaults to PREFERRED with no certificate verification.
Engineers should treat verify-full as the only acceptable mode for production deployments.

Mutual TLS (mTLS) for Database Authentication

Standard TLS authenticates the server to the client.
Mutual TLS extends this so the server also authenticates the client via a client certificate.
This is valuable for database connections because it provides cryptographic client identity independent of password-based authentication.

In PostgreSQL, mTLS is configured through pg_hba.conf with the cert authentication method, which maps the client certificate's Common Name (CN) or SAN to a database user.
MySQL supports mTLS via the REQUIRE X509 or REQUIRE SUBJECT clauses in CREATE USER statements.

mTLS introduces operational complexity around certificate issuance, rotation, and revocation.
Organizations typically use an internal CA (often managed through tools like HashiCorp Vault, cert-manager, or CFSSL) to automate short-lived certificate provisioning for database clients.

Performance Considerations

TLS adds overhead in two areas: connection establishment and steady-state data transfer.

Handshake latency: A TLS 1.3 handshake adds one round trip.
For TLS 1.2, it adds two.
TLS 1.3 also defines a 0-RTT resumption mode, but this feature has well-known replay attack implications and is not supported by major database server implementations for this reason; it should not be used for database connections.
Connection pooling (via PgBouncer, ProxySQL, or application-level pools) amortizes handshake cost across many queries, making this overhead negligible in well-architected systems.

Throughput overhead: AES-GCM with hardware acceleration (AES-NI, available on virtually all modern x86 and ARM server processors) adds roughly 2–5% CPU overhead specifically for the encryption and decryption of data in flight.
Total query latency impact will vary based on workload — CPU-bound query workloads will see a smaller relative impact than high-throughput, result-set-heavy workloads.
For most production workloads, TLS overhead is well within acceptable bounds.
Benchmarks from the PostgreSQL community show single-digit percentage throughput reduction for TLS-enabled connections on AES-NI capable hardware.

TLS session resumption: Both TLS 1.2 (via session tickets or session IDs) and TLS 1.3 (via PSK-based resumption) allow abbreviated handshakes for reconnecting clients.
Database connection pools that cycle connections can benefit from this, though support varies across database drivers and server implementations.

The practical recommendation is straightforward: enable TLS unconditionally.
The performance cost is minimal on modern hardware, and the security benefit is substantial.

Common Pitfalls

Silent fallback to plaintext: Some configurations allow the client to fall back to an unencrypted connection if TLS negotiation fails.
This can be exploited by an active attacker who interferes with the TLS negotiation.
Enforce require as a minimum, and verify-full as the target.

Expired or self-signed certificates without pinning: Self-signed certificates are acceptable if the client is configured to trust only that specific certificate (certificate pinning).
Without pinning, self-signed certificates offer no authentication value.

Incomplete certificate chains: The server must present the full chain from its leaf certificate to (but not including) the root CA, which is typically pre-distributed in client trust stores.
Missing intermediate certificates cause verification failures that are often worked around by disabling verification entirely — the correct fix is to repair the chain.
Note that some server configurations include the root CA in the presented chain; this is harmless, though unnecessary.

Outdated TLS versions: TLS 1.0 and 1.1 are deprecated (RFC 8996).
TLS 1.2 remains acceptable when configured with strong cipher suites, but TLS 1.3 should be preferred for its improved handshake performance and removal of legacy cryptographic options.

Key Points

  • TLS protects database connections against eavesdropping, tampering, and impersonation, but only when certificate verification is fully enabled.
  • Most database drivers default to modes that encrypt traffic without verifying the server's identity, leaving connections vulnerable to MITM attacks.
  • verify-full (or its equivalent) is the only TLS mode that provides complete protection, by validating both the CA chain and the server hostname.
  • verify-ca without hostname checking provides only partial protection: any certificate from the trusted CA, regardless of hostname, will be accepted.
  • TLS 1.3 reduces handshake latency to a single round trip and removes support for weak legacy cipher suites, making it the preferred version.
  • Mutual TLS enables cryptographic client authentication, eliminating reliance on passwords for database access control.
  • Connection pooling and hardware AES acceleration make the performance overhead of TLS negligible for the vast majority of database workloads.
  • Protocol-level TLS negotiation (e.g., PostgreSQL's SSLRequest) occurs in plaintext before encryption begins, making enforcement policies on both client and server essential.

References

E. Rescorla. "The Transport Layer Security (TLS) Protocol Version 1.3." RFC 8446, Internet Engineering Task Force, August 2018.

D. Cooper, S. Santesson, S. Farrell, S. Boeyen, R. Housley, W. Polk. "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile." RFC 5280, Internet Engineering Task Force, May 2008.

K. Moriarty, S. Farrell. "Deprecating TLS 1.0 and TLS 1.1." RFC 8996, Internet Engineering Task Force, March 2021.

The PostgreSQL Global Development Group. "PostgreSQL Documentation: SSL Support." PostgreSQL 16 Documentation, Chapter 19.9, 2023.

Oracle Corporation. "MySQL 8.0 Reference Manual: Using Encrypted Connections." MySQL Documentation, Section 6.3, 2023.

Newsletter

Signal
over noise.

Database deep-dives, delivered once a week. Storage engines, query optimization, and the data layer.

You will receive Databases Weekly.