If you’re managing a PostgreSQL database and handling sensitive data or PII, the answer is simple: You need data-at-rest encryption. This isn’t just a “nice-to-have” feature—it’s often a legal or regulatory requirement. Compliance auditors, security officers, and privacy-conscious customers all expect it.  But is this enough?  We think NO!

The reality check: No native TDE for Community PostgreSQL (Yet!)

Unlike some of its proprietary PostgreSQL-based counterparts, Community PostgreSQL doesn’t have TDE (Transparent Data Encryption) available. There is no open source TDE solution for PostgreSQL, but that’s changing. 

Cue the dramatic reveal music… Introducing pg_tde Beta!

Beta, you say, again?

Wait, how is it a beta again?

The initial version of pg_tde (now referred to as tde_heap_basic) was released as a Community PostgreSQL extension. It achieved encryption by processing data before it hit PostgreSQL’s shared buffers. This approach ensured broad compatibility with existing PostgreSQL deployments. However, it came with trade-offs:

  1. Performance — Encrypting data at this stage also effectively encrypts “data-in-use,” which sounds great until you see the performance cost multiple times higher than expected. 
  2. Table-only encryption — While individual tables were encrypted, indexes were not. And with PostgreSQL’s vast index types (and custom indexes from extensions), maintaining compatibility would be a constant uphill battle. 

To emphasize the importance of encrypting indexes, let’s start with what a database index is. In simple words, it’s a pointer to a data table that makes search more efficient. While there are many types of indexes, most of them have a copy of the data. This means that using them on encrypted information would allow access to and potentially leak encrypted information. Limiting the use of indexes in an enterprise setup is a struggle nobody asks for—it simply would not scale with the organization’s size.

This version of pg_tde is still available. The build of pg_tde limited to the tde_heap_basic access method is the only one currently available for Community PostgreSQL.

How is this new approach different?

To address the limitations of  tde_heap_basic, Percona’s team took a new approach. By applying two lightweight patches on top of the Community PostgreSQL (available in Percona Distribution for PostgreSQL), we enhanced the extensibility of the Storage Manager (SMGR) and Write-Ahead Log (WAL). As we hope to see them available in Community PostgreSQL, these patches are currently under review for Community PostgreSQL upstream submission as we think they will provide benefits to the Community far beyond just this application.

What does this version deliver thanks to these patches?

  • Index encryption support — no more unencrypted indexes.
  • Native replication compatibility works out of the box with PostgreSQL’s existing replication.
  • Minimal performance impact in early tests—initial tests report around 10% performance overhead for most data types without extra tuning. We expect this to lower with the time and effort spent evolving this approach.

The challenges of this approach

Tweaking the PostgreSQL core means we had to put a lot of extra effort into ensuring that these changes would not impact any existing users. One way to achieve that is to ensure that we only add extensibility while maintaining full binary compatibility. This means that the Percona Distribution for PostgreSQL is tightly coupled with PostgreSQL releases and adds these patches to each new version starting with 17. 

To ensure the stability of the changes, the patches are tested using PostgreSQL’s own regression tests, and our QA team puts extra effort into ensuring their stability. Currently, the whole solution is under a lot of scrutiny from both our internal and external testers and auditors to ensure stability and correctness. As you can expect, before hitting production readiness, many more tests will follow.

While every use case and database is different, we can also learn from past experiences. An added reassurance is that the team has extensive experience with TDE from other databases like MySQL and MongoDB, where Percona has already provided such solutions.

Envelope encryption model!

When you encrypt a table using pg_tde:tde_heap (whether via CREATE TABLE or ALTER TABLE), a table-specific encryption key is generated. This key, called internal key, is dedicated to that table and is stored in a keyring file (a file containing all internal keys for all the tables encrypted with pg_tde for a given database).

We achieve security for the solution by applying encryption to the internal keys before they are stored in a keyring file. The internal keys are encrypted with a principal key before storage. This principal key is the “master key” that controls access to all encrypted table keys for a given database. In a cluster environment, there may be multiple principal keys, as every database can configure encryption on its own.

Where is the principal key stored?

You can store it locally, but it’s not recommended for production. A locally stored principal key increases the risk of compromise and complicates key rotation and management.

The principal key should be stored in a Key Management System (KMS). Integration with KMS has been one of the requirements, even for the beta version. Supported KMS options include:

  • HashiCorp Vault
  • KMIP-compatible KMS

What’s so great about this approach?

  1. Performance and scalability — rotating a principal key doesn’t mean re-encrypting every table. The table keys stay put, only the wrapping (principal) key changes. 
  2. Better key management — KMS integration makes key rotation and revocation simple and centralized.
  3. Cloud-ready, multi-tenant friendly — each database in a multi-tenant cluster can have its own distinct principal key. This is a big deal for Kubernetes and cloud-native setups.

How do you try it out? 

Good news — pg_tde is open-source and ready to test. It’s included in Percona Distribution for PostgreSQL 17.2.1.

Here’s the quickstart:

  1. Load and create the extension
  2. Complete the key configuration

And then, you’re ready to roll.

This creates a table where all data is encrypted. Indexes are encrypted, too.

Encrypting an existing table

That’s it. The encryption magic happens behind the scenes. No funky setup scripts, no hand-holding required—just secure, encrypted tables with minimal fuss. And yes, it’s open source, so you can check the code yourself (do start the project and leave us some feedback when you do!).

What’s next?

What’s next, you ask? Full general availability for PostgreSQL TDE, of course! It’s in beta now, but with your feedback and the combined power of the PostgreSQL Community, we’re on the path to having TDE as a built-in, first-class citizen in PostgreSQL.

Got ideas? Bugs? Feedback? We’d love to hear from you. Join us in shaping the future of PostgreSQL encryption. The only thing more secure than encrypted data… is open-source encrypted data.

Check out the source code on the pg_tde GitHub project page!


Our PostgreSQL Performance Tuning eBook condenses years of database expertise into a practical guide for optimizing your PostgreSQL databases. Inside, you’ll discover our most effective PostgreSQL performance strategies derived from real-world experience.

 

Download now: PostgreSQL Performance Tuning

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Ram

Whether pg_tde can be used in other postgress variants like zalando