LLM WikiAccess-protected knowledge portal

WIKI

DBOS 2.29: PostgreSQL 하나로 내구성 있는 워크플로우를 운영하는 방법

별도 오케스트레이션 서버 없이 내구성 있는 워크플로우를 만들 수 있을까 Temporal, Conductor, Airflow 같은 오케스트레이션 도구는 강력하지만 운영 부담이 있다. Temporal은 별도 클러스터가 필요하고, 상태를 저장하는 데이터베이스도 따로 운영해야 한다. 소규모 팀이나 이미 PostgreSQL을 쓰는 서비스에게는 과한 설정이다. DBOS는 다른 접근을 선택했다. 이미 갖고 있는 PostgreSQL로 내구성

경로human/study/content/database-frontier/68-dbos-postgresql-durable-workflows-transactional-execution.md
카테고리Study
태그#airflow #durable #execution #infra #mysql #postgresql #study #transactional #workflows

별도 오케스트레이션 서버 없이 내구성 있는 워크플로우를 만들 수 있을까

Temporal, Conductor, Airflow 같은 오케스트레이션 도구는 강력하지만 운영 부담이 있다. Temporal은 별도 클러스터가 필요하고, 상태를 저장하는 데이터베이스도 따로 운영해야 한다. 소규모 팀이나 이미 PostgreSQL을 쓰는 서비스에게는 과한 설정이다.

DBOS는 다른 접근을 선택했다. 이미 갖고 있는 PostgreSQL로 내구성 있는 워크플로우를 실행한다. 별도 오케스트레이션 서버가 없고, 상태는 앱 데이터베이스에 함께 저장된다. 2026년 7월 30일 DBOS Transact 2.29.0이 릴리스됐고, 7월 15일에는 Go 패키지가 공개됐다. Java는 1.0 GA로 Python·TypeScript에 이어 세 번째 프로덕션 언어가 됐다.

이 챕터는 DBOS Transact v2.29.0(2026-07-30)과 공식 문서를 기준으로 한다. DBOS Cloud(관리형 서비스)와 DBOS Transact(자체 호스팅 라이브러리) 두 제품이 있으며, 여기서는 라이브러리 중심으로 다룬다.


핵심 아키텍처: PostgreSQL을 실행 레이어로 쓰는 방법

DBOS의 설계는 단순하다. 워크플로우 실행 중에 각 단계의 결과를 PostgreSQL에 저장한다. 프로세스가 죽어도 마지막으로 완료된 단계부터 재개한다.

Temporal vs DBOS 아키텍처 비교 전통 오케스트레이션 (Temporal) 앱 서버 Temporal Worker 내장 Temporal Server 별도 클러스터 운영 Temporal DB PostgreSQL / Cassandra 앱 DB 별도 PostgreSQL (앱 데이터) 구성요소: 앱 서버 + Temporal 클러스터 + Temporal DB + 앱 DB (최소 4가지) DBOS 앱 서버 DBOS 라이브러리 내장 @workflow @step 어노테이션 별도 프로세스 없음 다중 서버 → 동일 DB 공유 PostgreSQL (단일) 워크플로우 체크포인트 큐 · 스케줄 · 알림 상태 앱 데이터 (같은 트랜잭션) LISTEN/NOTIFY 스트림 구성요소: 앱 서버 + PostgreSQL (2가지, 기존 DB 재사용 가능) DBOS 핵심 원칙: 내구성 있는 실행은 새 인프라가 필요하지 않다 @DBOS.workflow() / @DBOS.step() → 각 단계 결과를 PostgreSQL에 체크포인트 저장 프로세스 재시작 시 마지막 완료 단계부터 재개 · 앱 데이터와 워크플로우 상태를 같은 트랜잭션으로 보호 LISTEN/NOTIFY 기반 스트림: 단일 Postgres에서 60K writes/s · ms 수준 지연 (2026-07 20배 향상) Python · TypeScript · Java 1.0 GA · Go (2026-07-15) 지원
DBOS vs 전통 오케스트레이션 아키텍처 비교

코드 수준에서 보면

from dbos import DBOS

@DBOS.workflow()
def process_order(order_id: str):
    # 각 step 결과가 PostgreSQL에 체크포인트된다
    validated = validate_order(order_id)   # step 1
    charged   = charge_payment(validated)  # step 2
    shipped   = ship_order(charged)        # step 3
    return shipped

@DBOS.step()
def charge_payment(validated):
    # 실패 후 재시작 시 validate_order는 다시 호출하지 않음
    # charge_payment 결과가 저장돼 있으면 저장된 값을 반환
    ...

실행 중 charge_payment 이후 프로세스가 죽으면, 재시작 후 ship_order부터 재개된다. validate_ordercharge_payment는 이미 체크포인트됐으므로 재실행하지 않는다. 정확히 한 번(exactly-once) 실행이 보장된다.


2026년 7월 주요 변화

동적 큐(Dynamic Queues)

기존에는 큐를 코드에서 정의하고 배포 시 생성했다. 이제 런타임에 데이터베이스를 통해 큐를 생성·수정·삭제할 수 있다. 배포 없이 동시성 한도와 속도 제한을 조정할 수 있어, 테넌트별 처리량 제어나 급격한 트래픽 변화 대응에 유용하다.

워크플로우 메타데이터(JSONB)

워크플로우 실행에 임의의 JSON 속성을 붙일 수 있다. 고객 ID, 테넌트, 지역, 요청 ID, 배포 환경 등 컨텍스트를 태깅하고, PostgreSQL JSONB GIN 인덱스로 빠르게 조회할 수 있다.

DBOS.set_workflow_attributes(
    {"customer_id": "cust_123", "region": "us-east-1", "priority": "high"}
)
-- 특정 고객의 실행 중 워크플로우 조회
SELECT workflow_uuid, status, attributes->>'customer_id'
FROM dbos_workflow_status
WHERE attributes->>'customer_id' = 'cust_123'
  AND status = 'RUNNING';

내구성 있는 스트림 20배 처리량 향상

내부 배치 처리를 도입해 동일 워크로드에서 처리량이 최대 20배 향상됐다. 핵심은 PostgreSQL LISTEN/NOTIFY 통합이다.

PostgreSQL LISTEN/NOTIFY는 단일 서버에서 60,000 writes/s와 밀리초 수준 지연을 처리한다. 별도 Kafka 클러스터 없이 신뢰성 있는 이벤트 전달이 가능한 임계점이다.

트랜잭셔널 데이터소스(Transactional Datasources)

2026년 7월의 가장 중요한 변화다. 앱 데이터베이스 연산과 DBOS 내구성 연산을 동일 트랜잭션에서 실행할 수 있다.

기존에는 앱 데이터 변경과 워크플로우 체크포인트가 별도 트랜잭션이었다. 앱 데이터는 저장됐는데 체크포인트가 실패하거나 그 반대가 되는 시나리오가 있었다. 트랜잭셔널 데이터소스는 이 경계를 없애 정확히 한 번 의미론을 완성한다.

@DBOS.step()
def update_inventory_and_checkpoint(order_id, quantity):
    # 앱 DB 업데이트와 DBOS 체크포인트가 한 트랜잭션으로 묶임
    # 어느 하나가 실패하면 둘 다 롤백
    db.execute("UPDATE inventory SET stock = stock - :qty", {"qty": quantity})
    # DBOS 상태도 같은 트랜잭션에서 커밋

Java 1.0 GA · Go 패키지 공개

Java가 프로덕션 수준이 됐다. DBOS 프로그래밍 모델 전체와 stable public API를 지원한다. 기업 내 Java 기반 백엔드에 DBOS를 도입할 수 있는 길이 열렸다. Go 패키지도 2026년 7월 15일 공개됐다.


Temporal과 비교

DBOS가 Temporal을 대체하는 것이 아니라 적합 사례가 다르다.

항목TemporalDBOS
추가 서버Temporal 클러스터 필요없음
데이터베이스전용 DB 별도 운영기존 PostgreSQL 재사용
트랜잭션 원자성앱 DB와 분리같은 트랜잭션 가능
수평 확장 상한매우 큼(Cassandra 가능)PostgreSQL 처리량 한계
상태 조회 방법Temporal SDK/UISQL 직접 쿼리
Java 지원성숙1.0 GA (2026-07)
Go 지원성숙공개 (2026-07-15)

PostgreSQL 수준의 처리량(수만 TPS)으로 충분하고 별도 오케스트레이션 클러스터를 피하고 싶다면 DBOS가 적합하다. 수백만 동시 워크플로우나 Cassandra 수준의 수평 확장이 필요하다면 Temporal이 더 맞는다.


운영 패턴

멀티 서버 배포

여러 서버 프로세스가 동일 PostgreSQL 시스템 데이터베이스를 공유한다. 서버 한 대가 죽어도 다른 서버가 해당 워크플로우를 이어받는다. 스케일 아웃은 서버 프로세스 추가만으로 가능하다.

프로그래매틱 일시정지·재시작

워크플로우 상태가 PostgreSQL 행으로 저장되므로 SDK로 직접 제어할 수 있다.

# 특정 조건의 워크플로우 일괄 일시정지
workflows = DBOS.list_workflows(attributes={"region": "us-east-1"})
for wf in workflows:
    DBOS.pause_workflow(wf.workflow_uuid)

# 나중에 재개
DBOS.resume_workflow(wf.workflow_uuid)

내구성 있는 스케줄과 알림

@DBOS.scheduled() 어노테이션으로 크론 기반 스케줄을 PostgreSQL에 저장한다. 서버 재시작 후에도 스케줄이 복원된다. DBOS.sleep() 역시 내구성 있게 구현되어 days~weeks 단위의 대기도 프로세스 재시작에 안전하다.


도입 검토 기준

DBOS가 잘 맞는 경우
이미 PostgreSQL을 운영하고 있고 추가 오케스트레이션 클러스터를 피하고 싶다.
앱 데이터와 워크플로우 상태를 같은 트랜잭션으로 보호해야 한다(Transactional Datasources).
워크플로우 상태를 SQL로 직접 조회하고 싶다.
동시 워크플로우 수가 수십만 이내이고 PostgreSQL 처리량 안에서 관리된다.
Python, TypeScript, Java, Go 중 하나 이상을 사용한다.
다른 선택지가 나은 경우
동시 실행 워크플로우 수가 수백만이고 Cassandra 수준의 수평 확장이 필요하다.
기존 Temporal 투자와 팀 숙련도가 있어 전환 비용이 크다.
PostgreSQL이 아닌 MySQL이나 MongoDB를 주 데이터베이스로 사용한다.
운영 주의사항
시스템 데이터베이스 연결 풀을 앱 연결 풀과 분리한다. 워크플로우 체크포인트 쓰기가 앱 쿼리 지연에 영향을 주지 않도록 한다.
DBOS Go(2026-07-15 공개)는 Python·TypeScript 대비 API 성숙도 차이가 있을 수 있다. 프로덕션 배포 전 충분한 검증이 필요하다.
PostgreSQL 연결 수가 늘어나므로 PgBouncer 같은 연결 풀러와 함께 쓰는 것이 좋다.
DBOS 도입 적합성 판단 기준

정리

DBOS의 가치는 "Temporal보다 쉬운 대안"에 있지 않다. 이미 있는 PostgreSQL을 내구성 있는 실행 레이어로 바꾸는 아이디어가 핵심이다.

워크플로우 상태와 앱 데이터를 같은 트랜잭션으로 묶는 Transactional Datasources, LISTEN/NOTIFY 기반 20배 향상된 스트림, 런타임 동적 큐, Java 1.0 GA로 진입 장벽이 낮아졌다.

PostgreSQL을 쓰는 팀이라면 "별도 오케스트레이션 클러스터 없이 내구성 있는 워크플로우를 실행할 수 있다"는 전제를 검토해볼 시점이다.

References