Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w2F44-0007KX-35 for pgsql-hackers@arkaria.postgresql.org; Mon, 16 Mar 2026 21:01:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w2F43-00Cwer-1a for pgsql-hackers@arkaria.postgresql.org; Mon, 16 Mar 2026 21:01:27 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w2F43-00Cwej-0Y for pgsql-hackers@lists.postgresql.org; Mon, 16 Mar 2026 21:01:27 +0000 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w2F40-00000000UO7-33Uw for pgsql-hackers@postgresql.org; Mon, 16 Mar 2026 21:01:26 +0000 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-48334ee0aeaso44278575e9.1 for ; Mon, 16 Mar 2026 14:01:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773694884; x=1774299684; darn=postgresql.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id:from :to:cc:subject:date:message-id:reply-to; bh=NgEWxSTZxiqmf0d9tPNmxG8LUaA5cYCgXPj0O1ShoMg=; b=fSHvi379MEMDhSmFnMPYsn79EzTVeRyQgE1TFKIJQhWwL2QBnhrMlfFoOp2bG72mV/ 8xG5auqmEQ7KC3r8ELEDaZnyxQOYzTga3PV/lfjp+JbeTk7tWX5UInMl6Ip5MpvfEWn4 FXilXb46g3Bns0EQfwKskWYWvvjQ5gswn80BLGFjYjxGQHM+7cMVde8tfc0gp4iIzY4t AfsAtyvNJRW7U/wZAIRm+OHDDMbCLg1W6IzNh6h5JYtiUrhUDMuYvafmRHZgnfi5VWS0 y3Hd9XLgnW5qaUj6KMI+UdTs1CKYBxcR30NFIUWZPrIG8Vkx0kM7z7lJTHIXVhS/PQqw A/BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773694884; x=1774299684; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NgEWxSTZxiqmf0d9tPNmxG8LUaA5cYCgXPj0O1ShoMg=; b=GLM3kki8Hji1e+NGPD4bU9GUOD5R+4Nm/0ASsRuaMIzHip1hyGb4E0WOsYbEBf2zec bS0ocZcmy4gZfSl9292kN95xINyaZqI5osamUYoQw6SSt7FLGcMH07ihRf2/aceRZ1Jo elDztzWUcA2kAGPHhTuog4pQq8xFnRtfst9uDcilLu6Jyn3UfPyYMsODESXOuGh/GbuO MXCN2Dzws+oS6NhQ2ULO2lmcbw09axJuiWUpyUpTAgco7cNqAgUNRNJcSwUBynGAdtAG OLhet3ek912TzKWed05vsiOyskbx/2fMJJeoBa1niwqR/423Aqh4I5FW7EpwuTgMz9kl WnQw== X-Forwarded-Encrypted: i=1; AJvYcCW3wEm5Pt9xvN1elLxEBBBGsYRynZEWcACXOVq0FXxWLuy412HfP2TjPKfdDHXW0SUcqDmFB23ImhdVsDgw@postgresql.org X-Gm-Message-State: AOJu0YzV771V0pzW6LEc573RDSMa47zk2/EpYVJh1adbG2JN6IpsxIUP Ln8eKCxcBRyOU/gKDmBP1/qs9jwKhMugxIGmzX7VenMbOQ6fqSkP+iL4khX0HrH02sE= X-Gm-Gg: ATEYQzxXoauk3TaMDLdNdXuBXxWzJrzeyXjktATqMTZzLY2R70QcSM3hvCODLK0zHqW w1GuQLfm61bgG87ARH9qDprFdnuLQjdk3xk2IwwX0tJC28iMEP8XfSYLd25IXdFoqKlCINFCQ9r F0DUcA9ZflcftIolVL7fZQgAXsJbzLm2LGe1qCmC8ddIAui+BK/n+J7ak8uc8yiJwVd2rr+ud1Z utktKuOey6lDA/Fjfpo8KNv2KXyhfZKaxi2yKPBdjEdV8NWNwF9N2Iaw9V1nE00Rx70sQcOS2eV rb/I5de4ecIP0WDAEWF70JGGhJJixuirXzaTaou7e1gMcIYAHPB9IZ8PWplweQINd7KPTWfo5lE d+wpMtG3ZujmITf+2Cr/g6MRYF1JKXvC1c3hHFVYmaX/taMRzF8F+IL5D2nwCIJL6Aw4/XC402i 6Dhji6CQA3NSJlHe1is2XNJy9ONDofjp2RuOt/zs5TqO6vo/t1hb3z5Xgzl7QuCd0zKKocWQv+F w== X-Received: by 2002:a05:600c:3104:b0:477:7ab8:aba with SMTP id 5b1f17b1804b1-485566e316dmr227534525e9.1.1773694883928; Mon, 16 Mar 2026 14:01:23 -0700 (PDT) Received: from [192.168.0.86] (84.123.225.106.dyn.user.ono.com. [84.123.225.106]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4856ea96f94sm21994095e9.6.2026.03.16.14.01.23 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 16 Mar 2026 14:01:23 -0700 (PDT) Message-ID: Date: Mon, 16 Mar 2026 22:01:22 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Read-only connection mode for AI workflows. To: Jack Bonatakis , pgsql-hackers References: <64f1c69a-ceff-4b17-8298-58f255d075fc@gmail.com> Content-Language: en-US From: Andrei Lepikhov In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 16/3/26 20:28, Jack Bonatakis wrote: > On Mon, Mar 16, 2026, at 2:08 PM, Andrei Lepikhov wrote: >> I believe the pg_readonly [1] extension does what you're looking for, so >> you might want to give it a try. > > Hi Andrei, > > Please correct me if I am mistaken, but it looks like pg_readonly > operates at the database or cluster level. Exactly. It works cluster-wide at the moment. But it is very simple to allow it to establish a read-only mode in a backend. That's exactly why I requested a full picture. > If I understand Mat's > proposal correctly, and based on my own experience integrating LLM-based > tools with databases, one might desire to set a particular connection to > be read-only while leaving the rest of the connections to operate > normally (read/write). Now, I would hope that someone building an AI > integration that is not intended to write to or manage the system would > be doing so off of a read-replica where pg_readonly would make more > sense, but I would wager that this will not always be the case. > >> Connection setup is usually not AI controlled while the SQL executed >> sometimes is. That's why being able to control read-only mode on the >> connection level would be useful. Ok, such a mode will reduce minor pg_readonly overhead down to almost zero. The practical questions I need to know in advance: 1. Is it OK to call the LOAD command at the beginning of connection establishment (make it dynamically loadable and strictly connection-dependent) 2. Should it be able to change the mode inside such a read-only session (let's say, under a superuser). > > Additionally, I believe this is the key point. Setting read-only at the > connection level alleviates any concern about an AI agent exploiting > misconfigured permissions to escalate its privileges (e.g. `select > unset_cluster_readonly(); drop table users;`). > >> Also, which commands do you want to restrict? For instance, vacuum >> isn't a DML command, but it can still change the state of table pages >> and pg_catalog. This functionality is now out of the Postgres core logic. It is not hard to add to the extension, though, let's say as a string GUC, where you may add any utility command you want to reject in read-only mode. So, depends on specific cases. > > From my perspective, many AI integrations would want to limit just > about anything that can change the state of the database. So yes, > vacuum, checkpoint, likely analyze (although I can see an argument for > allowing a read-only connection to run analyze), and other similar > commands, as well as of course traditional DML and DDL. > As I've said, it is easy unless you want to suspend internal services as well (like autovacuum). It is also doable within (I envision) the SMGR plugin, but a little more dangerous; this feature just needs more design and coding effort for a certain answer. > That said, once you start thinking about the precise scope of what > should be allowed or disallowed, the design space becomes quite large. > It may be worth clarifying the intended guarantees of such a feature > before discussing implementation details. Right now as an extension pg_readonly guarantees standard core XactReadOnly behaviour. > > I do think the underlying problem of safely exposing databases to > automated agents is becoming increasingly common, so it seems like a > useful area to explore. Thanks for your profound feedback! -- regards, Andrei Lepikhov, pgEdge