Mert Ersoy

We Gave Every Tenant a Postgres Connection String

What if you could give every tenant a direct Postgres connection string? Learn how we did it securely in a shared database with a custom TCP proxy.

We Gave Every Tenant a Postgres Connection String
#1about 2 minutes

The challenge of direct SQL access in multi-tenant SaaS

Providing direct Postgres access to customers is risky in a multi-tenant setup because standard roles leak metadata about other tenants.

#2about 1 minute

Why customers demand direct database access for BI tools

Customers prefer direct SQL access for their BI tools and data workflows, as REST APIs cannot replicate the power of SQL for joins and aggregations.

#3about 2 minutes

Why standard Postgres security features fail in multi-tenancy

Standard Postgres features like roles and row-level security are insufficient for multi-tenancy because they don't hide system catalog metadata, exposing other tenants' information.

#4about 2 minutes

Implementing virtual single tenancy with a protocol-level proxy

A protocol-level proxy creates virtual single tenancy by intercepting and rewriting queries, making a shared database appear isolated to each client without needing a database per customer.

#5about 2 minutes

A layered security model for the database proxy

The security model combines native Postgres roles to control data access with a proxy layer that rewrites system catalogs and blocks unsafe operations to control metadata visibility.

#6about 3 minutes

How the proxy rewrites system catalog queries

The proxy rewrites queries to system catalogs by adding WHERE clauses and subqueries to filter results based on the authenticated customer's schema and object identifiers.

#7about 1 minute

Handling the complexity of prepared statements

The proxy reassembles and rewrites the multi-part prepared statement protocol (parse, bind, execute) to ensure consistent security across all query types.

#8about 1 minute

Ensuring security with a fail-close guarantee

The proxy's core security guarantee is its fail-close mechanism, which rejects any query it cannot parse and prove safe, preventing unknown vulnerabilities.

#9about 1 minute

Preventing abuse with a denylist and rate limiting

A comprehensive denylist blocks dangerous SQL patterns like privilege escalation, while rate limits and statement timeouts prevent resource abuse on the shared database.

#10about 2 minutes

The native security layer and customer experience

A restrictive native Postgres role provides a final layer of security, enabling a seamless customer experience with a standard connection string for any SQL tool.

#11about 4 minutes

Understanding the tradeoffs and limitations of the proxy

The proxy solution has limitations, such as incompatibility with pg_dump and ongoing maintenance for the parser and denylist, but these were acceptable tradeoffs to meet customer needs.

#12about 1 minute

The reusable pattern of virtual single tenancy

The core takeaway is the reusable pattern of virtual single tenancy, where a proxy rewrites the wire protocol to provide secure access to a shared database.

Related jobs
Jobs that call for the skills explored in this talk.

Featured Partners

Related Articles

View all articles

From learning to earning

Jobs that call for the skills explored in this talk.