Skip to content

How to route read-only queries to a non-primary node while using Row-Level Security (RLS)? #152

@haininghu

Description

@haininghu

I use pgpool in front of several CloudSQL instances (1 primary node, multiple replicas). Most clients only perform simple read-only requests (SELECT), which are perfectly load-balanced by pgpool using statement-level load balancing. Only a few clients perform write requests, which are encapsulated within transactions and routed to the primary node by pgpool.
Now, I want to use PostgreSQL Row-Level Security (RLS) and am wondering: What is the best approach to do so? I’ve tried several methods:

Transaction with role

BEGIN;
SET ROLE ... <- set the role for RLS
SELECT ... <- the actual query
COMMIT;

Transaction with set_config

BEGIN;
SELECT set_config ... <- set config for RLS
SELECT ... <- the actual query
COMMIT;

CTE with set_config

WITH ctx AS (SELECT set_config(...)) <- set config for RLS
SELECT ... FROM ..., ctx WHERE ...;

The problem with all approaches

A SET or set_config always causes the following statements to be routed to the primary node. Even with the CTE solution, which, in my understanding, should not be the case since set_config within a CTE is meant to apply only to the following SELECT statement.
The only solution I found to prevent pgpool from routing everything to the primary is to mark set_config as "read-only" using read_only_function_list or write_function_list.

Question

Can you advise on how to use pgpool with statement-level load balancing enabled alongside row-level security?

Environment

pgpool2 version: 4.7.0
PostgreSQL version: 18.1

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions