microsoft/pg_durable
요약
Microsoft가 발표한 pg_durable는 PostgreSQL 내부에서 장기 실행 및 결함 허용(fault-tolerant) 워크플로를 구현하는 SQL 함수입니다. 별도의 외부 오케스트레이터 없이도 체크포인트를 통해 작업 중단 시 마지막 단계부터 실행을 재개할 수 있습니다.
핵심 포인트
- Postgres 내부에서 내구 실행(Durable execution) 구현 가능
- 충돌이나 재시작 시 마지막 체크포인트부터 자동 재개
- 벡터 임베딩 및 데이터 인제스트 파이프라인에 최적화
- 외부 인프라(Airflow, Temporal 등) 없이 데이터 근처에서 워크플로 관리
이미 Postgres에 상태(state)를 유지하고 있으며, 백그라운드 작업의 신뢰성을 확보하기 위해 cron 작업, 워커(workers), 큐(queues), 상태 테이블(status tables)을 일일이 조합하는 과정을 멈추고 싶은 팀들을 위한 장기 실행 및 결함 허용(fault-tolerant) SQL 함수입니다. SQL에서 워크플로(workflow)를 정의하면, pg_durable가 각 단계를 체크포인트(checkpoint)로 기록하며, 충돌(crash), 재시작 또는 단계 실패 후에도 실행을 재개할 수 있습니다.
내구 실행(Durable execution)은 이제 업계의 표준 패턴이며, pg_durable는 추가적인 서비스 인프라 없이 Postgres 내부로 이를 가져옵니다. 이는 컴퓨팅을 데이터 근처로 가져오려는 우리의 미션 중 일부입니다.
[IMG:1]
성능을 위해 설계되고 pg_durable가 내장된 Microsoft의 새로운 PostgreSQL 클라우드 서비스인 Azure HorizonDB에서 지금 바로 pg_durable를 사용해 보세요.
- 자신이 다루는 데이터 옆에 워크플로가 존재하기를 원하는 백엔드 및 데이터 엔지니어.
- 재시작 후에도 생존해야 하며 SQL로 감사(auditable)가 가능한 런북(runbooks)을 자동화하려는 DBA 및 SRE.
- 행(row), 문서(document) 또는 배치(batch) 단위로 내구 실행이 필요한 데이터 또는 AI 파이프라인을 구축하는 팀.
pg_durable 함수는 PostgreSQL이 실행하면서 진행 상황을 체크포인트로 기록하는 SQL 단계들의 그래프(graph)입니다. 데이터베이스가 충돌하거나 재시작되거나 특정 단계가 실패하더라도, 사용자가 수동으로 상태를 재구성할 필요 없이 마지막 내구 체크포인트(durable checkpoint)부터 실행이 재개됩니다.
-
벡터 임베딩(Vector embedding) 파이프라인: 청크(chunk) 분할, 임베딩 API 호출, 그리고
pgvector로 업서트(upsert). -
인제스트(Ingest) 파이프라인: 대규모 배치를 스테이징(stage), 중복 제거(deduplicate), 변환(transform) 및 게시(publish).
-
예약된 유지 관리(Scheduled maintenance): 블로트(bloat) 감지, 알림, 승인 대기 후 다음 작업 실행.
-
팬아웃 집계(Fan-out aggregation): 독립적인 쿼리를 병렬로 실행한 후 결과 결합.
-
외부 API 워크플로: SQL을 통한 데이터 보강(enrichment), 분류(classification) 및 웹훅(webhook) 스타일 호출.
-
pg_cron과 작업 테이블, 상태 컬럼, 재시도 카운터 및 폴링 워커(polling worker)를 사용하는 방식. -
Airflow, Temporal, Step Functions 또는 Argo와 같이 Postgres로 콜백을 호출하는 외부 오케스트레이터(orchestrator).
-
재시도 및 부분 완료를 조정하기 위한 큐(queue), 워커(workers) 및 별도의 상태 테이블(state table) 조합.
-
plpgsql
충돌(crash)이 발생하거나 장시간 실행되는 트랜잭션(long-running transaction)으로 인해 처음부터 다시 시작해야 할 때까지 작동하는 프로시저(procedure).
-
긴 작업 중간에 재시작한다는 것은 이미 성공한 작업을 다시 실행해야 함을 의미합니다.
-
단 하나의 행(row) 실패나 하나의 API 호출 실패가 수동 정리 및 불확실한 재실행(replay)으로 이어집니다.
-
긴 트랜잭션은 락(locks)을 점유하고, WAL(Write-Ahead Logging)을 증가시키며, 대규모 스케일에서 배치 작업(batch jobs)을 취약하게 만듭니다.
-
애플리케이션 계층(app tier)에서의 병렬 작업은 부분 실패(partial-failure) 버그와 드리프트(drift)가 발생할 수 있는 지점을 더 많이 만듭니다.
-
워크플로(workflow) 로직이 SQL, 워커(workers), 큐(queues), 대시보드(dashboards) 및 상태 테이블(status tables)에 흩어지게 됩니다.
-
워크플로 정의가 SQL로 이동하며
df.start(...)로 시작됩니다. -
재시도 상태(retry state), 진행 상황 추적(progress tracking) 및 체크포인팅(checkpointing)이 맞춤형 애플리케이션 코드 대신 Postgres 내부로 이동합니다.
-
일부 애플리케이션 계층의 워커, 큐 컨슈머(queue consumers) 또는 스케줄러 글루(scheduler glue)가 완전히 사라질 수 있습니다.
-
운영 가시성(operational visibility)은 데이터와 동일한 인증 및 백업 모델을 사용하는
df.instances와 같은 Postgres 테이블을 통해 확보됩니다. -
작업이 이미 단일
INSERT ... SELECT또는 하나의 일반적인 SQL 문입니다. -
내구성이 있는 백그라운드 실행(durable background execution)보다는 밀리초 미만(sub-millisecond)의 동기식 요청 처리가 필요합니다.
-
Postgres 환경에 확장 기능(extensions)을 설치하거나 백그라운드 워커(background worker)를 실행할 수 없습니다.
-
워크플로가 주로 Postgres 외부에서 존재하며 많은 이기종 시스템(heterogeneous systems)에 걸쳐 있습니다.
-
SQL 단계, 분기(branching), 루프(loops) 또는 HTTP 호출로 깔끔하게 매핑되지 않는 임의의 애플리케이션 로직이 필요합니다.
-
~>및|=>와 같은 조합 가능한 연산자(composable operators)를 사용하여 SQL에서 워크플로를 정의합니다. -
df.start()로 시작하고 인스턴스 ID(instance ID)를 반환받습니다. -
런타임이 단계 사이의 체크포인팅(checkpointing)과 함께 각 단계를 내구성 있게 실행하도록 합니다.
-
워크플로가 실행 중이거나 완료된 후 PostgreSQL에서 상태 및 결과를 쿼리합니다.
이 모델은 의도적으로 SQL 형태를 띠고 있습니다. 만약 특정 단계에서 임의의 코드, 비-HTTP SDK, 또는 풍부한 인메모리 제어 흐름(in-memory control flow)이 필요하다면, 해당 로직을 SQL 함수로 래핑(wrap)하거나, df.http()를 위해 HTTP 엔드포인트 뒤로 노출시키거나, 시스템의 해당 부분에 범용 오케스트레이터(general-purpose orchestrator)를 사용해야 할 수도 있습니다.
Durable (내구성)— 함수 상태가 PostgreSQL에 유지됩니다. 충돌(crash), 재시작, 장애 조치(failover) 상황에서도 생존합니다.
SQL-native (SQL 네이티브)— 조합 가능한 연산자(composable operators)를 사용하여 SQL로 함수를 정의합니다.
Database-aware (데이터베이스 인식)— 스케줄링, 조건, 병렬 실행을 위한 일급 기본 요소(first-class primitives)를 제공합니다.
Zero infrastructure (인프라 제로)— PostgreSQL 확장(extension)으로 실행됩니다. Redis, Temporal 또는 외부 서비스가 필요하지 않습니다.
-- 단계별로 데이터를 처리하는 내구성 있는 함수
SELECT df.start(
'SELECT id FROM documents WHERE processed = false LIMIT 100' |=> 'batch'
...
태그된 릴리스(Tagged releases)는 GitHub 릴리스 자산(release assets)으로부터 amd64용 PostgreSQL 17 및 18용 Debian 패키지를 게시합니다. 패키지 이름은 pg-durable-postgresql-<PG major>_<pg_durable version>-1_<arch>.deb 형식입니다.
이 패키지는 확장 라이브러리(extension library), 제어 파일(control file), SQL 업그레이드 파일을 일치하는 PostgreSQL 설치 디렉토리에 설치합니다.
패키지를 설치한 후, pg_durable을 shared_preload_libraries에 추가하고, PostgreSQL을 재시작한 다음, 구성된 pg_durable 데이터베이스에 확장을 생성하십시오:
CREATE EXTENSION pg_durable;
기본 pg_durable 데이터베이스는 postgres입니다. 백그라운드 워커(background worker) 구성 및 권한 설정에 대해서는 사용자 가이드(User Guide)를 참조하십시오.
릴리스 자산에는 소스 빌드를 위한 소스 아카이브(source archives)도 포함되어 있습니다.
- PostgreSQL 17 또는 18
- Rust (nightly)
- cargo-pgrx 0.16.1
메인 브랜치(main branch)의 사전 빌드(prebuild)는 PostgreSQL 17을 설치하고, pg_durable을 빌드하며, 확장이 준비된 상태로 ~/.pgrx 아래에 로컬 클러스터(local cluster)를 준비합니다. PostgreSQL이 실행된 상태로 유지되지 않으므로, 작업을 시작할 때 실행하십시오.
# PostgreSQL 시작
./scripts/pg-start.sh
# 연결
...
준비된 사전 빌드가 없는 브랜치에서는 pg-start.sh를 실행하십시오. 첫 실행 시 확장을 빌드하고 설치합니다(몇 분 정도 소요될 수 있습니다):
./scripts/pg-start.sh
VS Code Dev Container (.devcontainer/)는 Rust, cargo-pgrx, PostgreSQL 17이 사전 설치된 환경을 제공합니다. 일반 로컬 머신의 경우, .devcontainer/onCreateCommand.sh의 단계를 따라 툴체인(toolchain)을 먼저 설치하십시오.
# 빌드, PostgreSQL 초기화 및 확장 기능(extension) 설치
# 시간이 다소 소요됩니다 - 다른 일을 하고 오셔도 좋습니다
./scripts/pg-start.sh
...
pg-start.sh
postgres 슈퍼유저(superuser)를 포함하여 새로운 로컬 데이터 디렉터리를 부트스트랩(bootstrap)하며, 현재 OS 사용자에 대한 일치하는 슈퍼유저 역할(role)도 생성하여 기본 로컬 psql 사용이 계속 작동하도록 합니다. 표준 부트스트랩 역할을 명시적으로 강제하려면 -U postgres를 사용하십시오.
# 빌드 및 테스트
./scripts/test-e2e-docker.sh --rebuild
# 선택 사항: ACR에 배포 (pg_durable이 포함된 커스텀 PG17 이미지용)
...
CREATE EXTENSION pg_durable는 PUBLIC에 어떠한 권한도 부여하지 않습니다. 확장 기능을 설치한 후, 관리자는 애플리케이션 역할(application roles)에 명시적으로 액세스 권한을 부여해야 합니다. 행 수준 보안 (Row-level security (RLS))은 각 사용자가 자신의 내구적 함수(durable function) 인스턴스 및 노드만 보고 관리할 수 있도록 보장합니다.
애플리케이션 역할에 권한 부여:
-- CREATE EXTENSION 이후 특정 역할에 권한 부여
SELECT df.grant_usage('app_role');
또는, 간접 역할(indirection role)을 생성하고 애플리케이션 역할에 멤버십을 부여하십시오:
-- pg_durable 액세스를 위한 공유 역할 생성
CREATE ROLE pg_durable_user NOLOGIN;
SELECT df.grant_usage('pg_durable_user');
...
개별 권한 부여, 액세스 취소 및 업그레이드된 설치본의 보안 강화(hardening)에 대한 전체 목록은 사용자 가이드(User Guide) — 권한 부여(Privilege Grants) 섹션을 참조하십시오.
참고: GRANT EXECUTE ON ALL FUNCTIONS는 권한 부여가 실행될 때 존재하는 함수에만 적용됩니다. ALTER EXTENSION pg_durable UPDATE로 pg_durable을 업그레이드한 후에는, 새로운 함수에 접근할 수 있도록 df.grant_usage('role')를 다시 실행하거나(또는 수동 권한 부여를 다시 수행) 하십시오.
핵심 사항:
- 백그라운드 워커 역할 (
pg_durable.worker_roleGUC, 기본값:postgres)은 반드시 슈퍼유저(superuser)여야 합니다. 이 역할은 모든 사용자의 인스턴스를 관리하기 위해 RLS를 우회합니다. - 사용자는
df.instances/df.nodes에 대해SELECT+INSERT권한을 가지며,df.cancel()을 위한 인스턴스의 컬럼 수준UPDATE (status, updated_at)권한을 가집니다. - 식별 컬럼 (
submitted_by
)는 사용자에 의해 수정될 수 없습니다 — 각 사용자는 df.vars를 통해 자신만의 변수 네임스페이스를 가집니다.
owner 컬럼과 RLS (Row-Level Security, 행 수준 보안)를 사용하여 사용자별 스코핑 (per-user scoping)을 수행합니다. 슈퍼유저 (Superusers)는 RLS를 우회하지만, DSL 함수는 명시적 필터를 통해 여전히 호출한 사용자에게 스코핑됩니다. 비밀 정보를 평문으로 저장하는 것을 피하십시오.
모든 풀 리퀘스트 (Pull Requests)는 머지 (Merge) 전 다음 체크를 통과해야 합니다:
포맷 체크 (Format Check) — cargo fmt --check
Clippy 및 테스트 (Clippy & Tests) — cargo clippy, 단위 테스트 (cargo pgrx test pg17), pg_regress 테스트, 그리고 E2E (End-to-End) 테스트
CI 워크플로우는 .github/workflows/ci.yml에 정의되어 있습니다. 이는 pgrx를 사용하여 PostgreSQL을 다운로드하고 관리합니다.
pg_durable에는 두 가지 테스트 스위트 (Test Suites)가 있습니다:
- PostgreSQL의 표준 테스트 프레임워크를 사용하여 핵심 DSL 기능에 대해 수행하는 빠르고 결정론적인 (deterministic) 테스트:
테스트 SQL은sql/에 위치하며, 예상 출력은expected/에 있습니다. PGXS는 루트Makefile에 구성되어 있습니다.
make test-regress # 전체 리셋 + 실행
make installcheck # 실행만 수행 (PostgreSQL이 이미 실행 중이어야 함)
- pgrx PostgreSQL을 사용한 복잡한 로컬 통합 테스트:
./scripts/test-e2e-local.sh # 특수 재시작/설정 단계를 포함한 모든 로컬 SQL E2E 테스트
./scripts/test-e2e-local.sh 04_parallel # 특정 테스트
./scripts/test-e2e-local.sh --default-build-phases # 기본 빌드 단계 그룹만 수행
자세한 내용은 tests/e2e/를 참조하십시오.
- 사용자 가이드 (User Guide) — 예제를 포함한 전체 사용 가이드
- MVP 가이드 (MVP Guide) — 구현 세부 사항 및 내부 구조
- 예제 (Examples) — 예제 컨벤션 및 스모크 체크 (smoke-check) 안내
pg_durable는 PostgreSQL 확장 프로그램 (pgrx로 빌드됨)입니다 — 모든 것은 PostgreSQL 서버 내부에서 실행되며, 외부 서비스는 없습니다. 이 확장 프로그램은 함수 그래프를 구축하기 위한 SQL DSL을 노출하며, 두 개의 하위 수준 Rust 라이브러리 위에서 이를 내구성 있게 (durably) 실행하는 백그라운드 워커 (background worker)를 등록합니다:
- duroxide — 오케스트레이션 런타임 (orchestration runtime: 결정론적 재생 (deterministic replay), 체크포인트 (checkpoints), 하위 오케스트레이션 (sub-orchestrations), 타이머 (timers))을 제공하는 내구성 있는 태스크 프레임워크 (durable task framework).
- duroxide-pg — duroxide를 위한 PostgreSQL 기반 상태 제공자 (state provider). 런타임 상태 (인스턴스 (instances), 히스토리 (history), 작업 큐 (work queues))를 확장 프로그램(extension)이 소유한 전용
duroxide.*스키마에 영구 저장합니다.
┌────────────────────────────────────────────────────────────────────┐
│ PostgreSQL │
│ │
...
만약 상태를 PostgreSQL에 영구 저장하면서 Rust, Python 또는 Node에서 내구성 있는 함수 (durable functions)를 작성하고 싶다면, 호스트 언어에서 duroxide와 duroxide-pg를 직접 사용할 수 있습니다. pg_durable는 SQL로 작성하는 것을 선호할 때 이 두 조합 위에서 구축하게 되는 것입니다.
Preview - 이 프로젝트는 현재 프리뷰 (preview) 단계입니다.
버그 보고 및 기능 요청은 GitHub Issues를 사용해 주세요. 보안 취약점은 공개된 GitHub 이슈를 통해 보고하지 마십시오. 대신 SECURITY.md의 지침을 따르시기 바랍니다.
이 프로젝트는 Microsoft 오픈 소스 행동 강령 (Open Source Code of Conduct)을 채택했습니다. 자세한 내용은 행동 강령 FAQ를 참조하거나 질문 또는 의견이 있는 경우 opencode@microsoft.com으로 문의하십시오.
Microsoft는 소프트웨어 제품 및 서비스의 보안을 엄격하게 다룹니다. 공개된 GitHub 이슈를 통해 보안 취약점을 보고하지 마십시오. 보안 보고 지침은 SECURITY.md를 참조하십시오.
pg_durable는 Microsoft로 텔레메트리 (telemetry)를 전송하지 않습니다.
이 프로젝트에는 프로젝트, 제품 또는 서비스에 대한 상표나 로고가 포함되어 있을 수 있습니다. Microsoft 상표 또는 로고의 허가된 사용은 Microsoft의 상표 및 브랜드 가이드라인 (Trademark & Brand Guidelines)을 따르며 이를 준수해야 합니다. 이 프로젝트의 수정 버전에서 Microsoft 상표 또는 로고를 사용하는 것은 혼란을 야기하거나 Microsoft의 후원을 암시해서는 안 됩니다. 제3자의 상표 또는 로고 사용은 해당 제3자의 정책을 따릅니다.
PostgreSQL License
AI 자동 생성 콘텐츠
본 콘텐츠는 GitHub Trending All (daily)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기