Cloud SQL for PostgreSQL이 2026년 7월 24일 릴리스 노트로 failover slot 지원을 GA로 발표했어요. logical replication을 쓰면서 DR switchover나 replica failover를 하는 환경에서 slot이 살아남게 하는 기능이에요.

CSP 릴리스 노트를 읽을 때마다 확인해야 하는 게 하나 있습니다. 이게 그 벤더가 만든 기능인지, 아니면 upstream 기능을 이제 노출한 것인지 살펴봐야 합니다. 이번 건은 후자입니다. failover slot은 PostgreSQL 17 코어 기능이고, AWS와 Azure도 이미 지원합니다. GCP가 늦게 합류한 쪽입니다.

그렇다고 릴리스 노트가 무의미하지는 않습니다. 관리형 서비스는 upstream 기능을 노출할 때 파라미터 이름을 자기 방식으로 바꾸고, 조건을 붙입니다. 실무에서 걸리는 건 그 차입니다. 3사 문서를 나란히 놓고 정리했습니다.

왜 slot이 failover에서 사라지면 곤란한가

logical replication slot은 primary에만 존재했습니다. standby로 넘어가지 않았습니다. 그래서 failover가 일어나면 새 primary에는 그 slot이 없습니다.

flowchart TD
    P[primary
logical slot] -->|WAL 전송| S[standby] P -->|변경 스트림| SUB[구독자] S -.->|failover| NP[새 primary] NP --> Q{slot이
넘어왔나} Q -->|아니오| R[구독자 재동기화
초기 스냅샷부터] Q -->|예| C[구독자 그대로
이어서 수신]

slot이 없으면 구독자는 어디서부터 받아야 할지 모릅니다. 새로 slot을 만들면 그 시점부터 시작하므로, 옛 primary에서 마지막으로 읽은 지점과 새 slot 생성 시점 사이의 변경이 비게 됩니다. 안전하게 가려면 초기 스냅샷부터 다시 떠야 합니다. 수 TB 규모 CDC 파이프라인에서 이건 몇 시간에서 며칠짜리 작업입니다.

문제는 이 손실이 HA 구성을 갖췄다고 방지되지 않는다는 점입니다. HA는 데이터를 지키지만 slot은 데이터가 아닙니다. failover는 성공했는데 CDC만 끊기는 상황이 정확히 이 지점에서 나옵니다.

PostgreSQL 17이 한 일

17에서 slot 동기화가 코어에 들어왔습니다. 동작은 이렇습니다. standby에 slotsync worker가 붙어 주기적으로 primary에 물어보고, failover 속성이 켜진 logical slot을 로컬에 만들거나 갱신합니다. 동기화가 필요 없어진 slot은 worker가 알아서 지웁니다.

켜려면 여러 조건이 맞아야 합니다.

-- 구독자 쪽: failover 옵션을 켜고 subscription 생성
CREATE SUBSCRIPTION mysub
  CONNECTION 'host=... dbname=...'
  PUBLICATION mypub
  WITH (failover = true);

-- publisher 쪽에서 확인
SELECT slot_name, slot_type, failover FROM pg_replication_slots;

failover 열이 t여야 동기화 대상이 됩니다. 여기가 첫 번째 함정입니다. 서버 파라미터를 다 맞춰 놓고도 subscription에 failover = true를 빼면 아무 slot도 동기화되지 않습니다. 3사 문서가 모두 이 문장을 따로 적어 둔 이유입니다. 이미 만들어 둔 subscription이 있으면 ALTER SUBSCRIPTION ... SET (failover = true)로 바꿔야 합니다.

서버 쪽 요구사항은 네 갈래입니다. standby에 sync_replication_slots를 켜고, hot_standby_feedback도 켭니다. standby와 primary 사이에 물리 replication slot이 있어야 하므로 standby의 primary_slot_name이 설정돼 있어야 합니다. 그리고 primary의 synchronized_standby_slots에 그 물리 slot 이름을 넣어, logical slot이 standby가 아직 받지 못한 지점보다 앞서 나가지 못하게 막습니다.

마지막 항목을 빼먹기 쉬운데, 이걸 안 걸면 동기화는 도는 것처럼 보이지만 failover 순간에 구독자가 새 primary에 없는 WAL을 요구하는 상태가 될 여지가 남습니다.

17 이전 버전은 코어에 이 기능이 없습니다. EDB의 pg_failover_slots extension으로 같은 일을 했고, 관리형 서비스 중에는 이 extension을 제공하는 곳이 있습니다.

3사 비교

같은 upstream 기능인데 파라미터 이름이 셋 다 다릅니다. 문서를 옮겨 다니며 설정할 때 이 표가 필요합니다.

항목Cloud SQL (GCP)RDS for PostgreSQL (AWS)Flexible Server (Azure)
최소 버전PostgreSQL 17PostgreSQL 17PostgreSQL 17
추가 조건Enterprise Plus edition, Advanced DR명시 없음명시 없음
logical decoding 활성화cloudsql.logical_decoding=onrds.logical_replication=1wal_level=logical
standby 동기화 활성화sync_replication_slots=onsync_replication_slots=1sync_replication_slots
standby feedbackhot_standby_feedback=onhot_standby_feedback=1hot_standby_feedback
동기화 대상 DB 지정cloudsql.logical_slot_sync_dbnamerds.logical_slot_sync_dbname문서에 명시 없음
primary 쪽 대기 지정cloudsql.synchronized_standby_replicassynchronized_standby_slots문서에 명시 없음
17 이전 대안문서에 명시 없음문서에 명시 없음pg_failover_slots extension
failover 후 구독자 작업PSA 엔드포인트 사용 시 자동 재연결ALTER SUBSCRIPTION으로 새 primary 지정자동 보존

추상화 수준이 갈리는 지점

표에서 가장 눈여겨볼 행은 primary 쪽 대기 지정입니다.

AWS는 synchronized_standby_slots에 물리 replication slot 이름을 넣으라고 합니다. upstream 파라미터 그대로입니다. 그 slot 이름을 알아야 하고, 인스턴스를 재구성하면 값을 손봐야 합니다.

GCP는 cloudsql.synchronized_standby_replicas에 replica 인스턴스 이름을 넣으라고 합니다. 물리 slot 이름이 아니라 GCP 리소스 이름입니다. 내부에서 인스턴스 이름을 slot 이름으로 옮겨 준다는 뜻이고, 사용자가 PostgreSQL 내부 식별자를 몰라도 됩니다. 대신 그 매핑이 어떻게 되는지는 밖에서 안 보입니다.

이 차이가 두 서비스의 성격을 보여줍니다. AWS는 upstream 파라미터를 그대로 열어 주고 접두사만 붙이는 쪽이고, GCP는 자기 리소스 모델로 감싸는 쪽입니다. 어느 쪽이 낫다기보다, 셀프 호스팅 경험을 그대로 옮기려면 AWS가 편하고 PostgreSQL 내부를 몰라도 쓰게 하려면 GCP가 편합니다.

failover 이후 구독자가 해야 하는 일

AWS 문서는 standby가 승격된 뒤 구독자가 subscription을 새 인스턴스로 바꿔야 한다고 적습니다. slot은 살아 있으니 재동기화는 필요 없지만 접속 대상은 사람이 바꿔 줍니다.

GCP는 구독자가 private services access DNS 쓰기 엔드포인트로 접속해 있으면 switchover나 failover 뒤 자동으로 새 primary에 재연결된다고 안내합니다. 엔드포인트가 이름으로 고정되어 있고 그 이름이 새 primary를 가리키게 바뀌기 때문입니다. 같은 주에 프리뷰로 나온 AlloyDB write endpoint와 같은 발상입니다.

다만 GCP 문서에도 단서가 붙습니다. 승격된 replica에 남은 옛 primary의 orphaned slot은 수동으로 지워야 하고, 구독자가 그 옛 slot에 계속 붙으려 하는 경우가 있습니다. 자동 재연결이 모든 잔여물을 정리해 주지는 않습니다.

Aurora는 어떤가

여기는 정확히 적어야 합니다. AWS가 문서로 명시한 페이지는 “Managing logical slot synchronization for RDS for PostgreSQL"이고, 대상을 RDS for PostgreSQL 17로 적고 있습니다. Aurora PostgreSQL에 대한 동일한 안내 페이지는 확인하지 못했습니다.

Aurora는 read replica가 스토리지를 공유하는 구조라 물리 replication slot의 의미가 RDS와 다릅니다. 위 파라미터 조합이 그대로 통한다고 단정할 근거를 찾지 못했으니, Aurora를 쓴다면 엔진 버전과 파라미터 그룹에서 sync_replication_slots가 실제로 노출되는지 확인하고 테스트 클러스터에서 failover를 걸어 보는 편이 안전합니다. 검색에 잡히는 “Aurora 17도 된다"는 서술은 대부분 커뮤니티 글이라 1차 출처로 삼기 어렵습니다.

셀프 호스팅에서 확인하는 법

관리형 대신 직접 운영하는 경우 설정과 검증은 이렇습니다.

# primary
wal_level = logical
synchronized_standby_slots = 'standby_phys_slot'

# standby
primary_slot_name = 'standby_phys_slot'
hot_standby_feedback = on
sync_replication_slots = on

동기화가 실제로 되고 있는지는 standby에서 확인합니다.

-- standby에 slot이 만들어졌는지, 어디까지 따라왔는지
SELECT slot_name, failover, synced, restart_lsn, confirmed_flush_lsn
FROM   pg_replication_slots
WHERE  slot_type = 'logical';

synced 열이 t면 slotsync worker가 만든 복제본입니다. 수동으로 한 번 당겨 보려면 standby에서 SELECT pg_sync_replication_slots();를 실행합니다.

primary 쪽에서는 logical slot이 얼마나 뒤처져 있는지 봅니다.

SELECT slot_name, slot_type, failover,
       restart_lsn,
       pg_current_wal_lsn() - restart_lsn AS lag_bytes
FROM   pg_replication_slots
ORDER  BY slot_type, slot_name;

synchronized_standby_slots를 걸면 logical slot의 진행이 물리 slot에 묶이므로, standby가 멈추면 primary의 WAL이 쌓인다는 점을 같이 알고 있어야 합니다. 이 파라미터는 안전을 사는 대신 standby 장애를 primary 디스크 문제로 번지게 만드는 통로가 됩니다. restart_lsn 지연을 알림에 걸어 두는 게 좋습니다.

정리

Cloud SQL 릴리스 노트 한 줄을 따라가면 결국 PostgreSQL 17 코어 기능에 도착합니다. 3사가 모두 지원하고, 최소 버전도 셋 다 17입니다. 차이는 기능 유무가 아니라 파라미터 이름과 추상화 수준, 그리고 failover 이후 구독자 재연결을 누가 처리하느냐에 있습니다.

GCP만 Enterprise Plus edition과 Advanced DR을 요구한다는 점은 비교할 때 짚어 둘 만합니다. 기능이 있다는 것과 지금 쓰는 요금제에서 쓸 수 있다는 것은 다른 이야기입니다.

어느 클라우드를 쓰든 첫 번째 함정은 같습니다. subscription에 failover = true가 걸려 있지 않으면 서버 파라미터를 전부 맞춰도 아무 slot이 동기화되지 않습니다. 설정을 끝냈다고 생각한 시점에 pg_replication_slotsfailover 열부터 확인하는 게 순서입니다.

참고

이 블로그의 관련 글로는 PostgreSQL 19의 logical replication과 sequencePostgreSQL 19의 wal_level 동적 floor가 있어요.