#9141·gel

Gel Configuration Issues for Logical Replication

Author: chuckyQCreated May 1, 2026Updated May 1, 2026
  • Gel Version: 6.11+e4f7b57
  • Gel CLI Version: Gel CLI 7.10.2+e00c46c
  • OS Version: Ubuntu 24.04.3 LTS

Steps to Reproduce:

  1. Initialize a Gel instance on RDS (I used the CloudFormation yaml file)
  2. Use psql to log into the cluster
  3. Run the following query to find the tables with missing primary keys:
SELECT table_schema, table_name
    FROM information_schema.tables tbl
    WHERE table_type = 'BASE TABLE'
    AND table_schema NOT IN ('pg_catalog', 'information_schema', 'pglogical')
    AND NOT EXISTS (SELECT 1
                    FROM information_schema.key_column_usage kcu
                    WHERE kcu.table_name = tbl.table_name
                    AND kcu.table_schema = tbl.table_schema);

To fix, I inserted my own primary keys as an auto-incrementing integer.

  1. Certain views and functions rely on data types of the form reg* that cause the blue/green deployment to fail. To fix this, I dropped these from databases in the blue cluster and recreated them on the green cluster. On my cluster, the following objects that caused issues were:
  • "edgedbsql_v6_2f20b3fed0".pg_type view
  • "edgedbsql_v6_2f20b3fed0"._pg_truetypmod function
  • "edgedbsql_v6_2f20b3fed0"._pg_truetypid function
  • "edgedbsql_v6_2f20b3fed0".pg_type_ materialized view

I used the following query to find the problem columns (this was provided in the RDS logs):

WITH RECURSIVE oids AS (
    SELECT oid FROM pg_catalog.pg_type t WHERE t.typnamespace =
    (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = 'pg_catalog') AND
        t.typname IN ('regcollation', 'regconfig', 'regdictionary', 'regnamespace', 'regoper', 'regoperator', 'regproc', 'regprocedure')
        UNION ALL SELECT * FROM (WITH x AS (SELECT oid FROM oids) SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typbasetype = x.oid AND typtype = 'd' UNION ALL
        SELECT t.oid FROM pg_catalog.pg_type t, x WHERE typelem = x.oid AND typtype = 'b' UNION ALL
        SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_class c, pg_catalog.pg_attribute a, x WHERE
            t.typtype = 'c' AND t.oid = c.reltype AND c.oid = a.attrelid AND NOT a.attisdropped AND a.atttypid = x.oid UNION ALL
            SELECT t.oid FROM pg_catalog.pg_type t, pg_catalog.pg_range r, x
                WHERE t.typtype = 'r' AND
                r.rngtypid = t.oid AND
                r.rngsubtype = x.oid) foo)
    SELECT relnamespace, relname, attname, reltype, nspname, nspowner  FROM        pg_catalog.pg_class c, pg_catalog.pg_namespace n, pg_catalog.pg_attribute a
        WHERE c.oid = a.attrelid AND
        NOT a.attisdropped AND
        a.atttypid IN (SELECT oid FROM oids) AND
        c.relkind IN ('r', 'm', 'i') AND
        c.relnamespace = n.oid AND
        n.nspname !~ '^pg_temp_' AND
        n.nspname !~ '^pg_toast_temp_' AND
        n.nspname NOT IN ('pg_catalog', 'information_schema');

The output from the command was the following:

          nspname        | relname  |   attname
-------------------------+----------+--------------
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typsubscript
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typinput
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typoutput
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typreceive
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typsend
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typmodin
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typmodout
 edgedbsql_v6_2f20b3fed0 | pg_type_ | typanalyze

After backtracking what I needed to delete to make these columns drop, I found the objects that were causing the issue.

  1. DDL was not disabled and there is no clear way to disable it through Gel. To fix, I added the following function (provided by the AWS documentation) manually to each database in the underlying Postgres cluster:
CREATE OR REPLACE FUNCTION block_ddl_bg() RETURNS event_trigger   
SECURITY DEFINER  
AS $$  
DECLARE  
    -- Define allowed users and roles here  
    allowed_users TEXT[] := ARRAY['rdsadmin', 'rdsrepladmin'];  
    allowed_roles TEXT[] := ARRAY['rdsrepladmin'];  
BEGIN  
    -- Check if either the session user or current role is allowed  
    IF NOT (session_user = ANY(allowed_users) OR current_role = ANY(allowed_roles)) THEN  
        RAISE EXCEPTION 'DDL operations are blocked to prevent Blue Green Deployment replica degradation. User: %, Role: %, Status: BLOCKED',   
            session_user, current_role;  
    END IF;  
END;  
$$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER block_ddl_trigger ON ddl_command_start  

EXECUTE FUNCTION block_ddl_bg();

After performing all of these configuration changes, I was able to upgrade my Postgres cluster from 16 to 17.

I know the current procedure still requires a full dump-and-restore when changing Gel versions, but this is a good start for the Postgres major version upgrade and maybe Gel can support it.