9.7 KiB
title, source_type, url, archive_url, status, confidence, tags, related_projects, related_branches, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | tags | related_projects | related_branches | created | last_reviewed | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Transactional Outbox Pattern — microservices.io (Chris Richardson) | official-doc | https://microservices.io/patterns/data/transactional-outbox.html | raw | medium |
|
|
|
2026-05-27 | 2026-05-27 |
Transactional Outbox Pattern — microservices.io (Chris Richardson)
Layer:
raw/official-docs/— Chris Richardson 의 microservices.io 패턴 카탈로그 중 "Transactional Outbox" 페이지 verbatim 발췌. dual-write 문제와 OUTBOX 테이블 기반 해결책의 1차 인용 출처.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-repository-access-permission-contract | D7 (Repository 가 도메인 이벤트 발행 책임을 가질지, 아니면 outbox 테이블 write 만 책임지고 별도 relay 가 발행할지) 결정의 근거 |
| raw/branch-notes/feature-domain-event-outbox-contract | OUTBOX 테이블 + 별도 message relay 채택의 1차 근거 — "dual write 문제" 정의와 단일 local transaction 해결책 |
컨텍스트
ca-tmpl 이 도메인 이벤트를 어떻게 외부 메시지 브로커로 안전하게 전달할지의 청사진을 결정해야 한다. 가장 흔한 함정인 "DB commit 후 메시지 발행 실패" 또는 "메시지 발행 후 DB rollback" 의 inconsistency 를 방지하기 위한 표준 패턴이 transactional outbox. 본 raw 는 패턴 정의와 force/result 의 1차 출처.
출처 / Source
- 원본 URL: https://microservices.io/patterns/data/transactional-outbox.html
- 아카이브 URL:
- 저자 / 조직: Chris Richardson — microservices.io (personal pattern catalog). 별도 vendor 의 공식 문서 아님.
- 발행일: rolling docs (페이지에 "Copyright © 2026" 표기, 최초 작성 시점 명시는 없음)
- 마지막 확인일: 2026-05-27
핵심 인용 / Key quotes (verbatim)
[§Context] "A service command typically needs to create/update/delete aggregates in the database and send messages/events to a message broker."
[§Context] "The command must atomically update the database and send messages in order to avoid data inconsistencies and bugs."
[§Problem] "How to atomically update the database and send messages to a message broker?"
[§Forces] "Messages must be sent to the message broker in the order they were sent by the service."
[§Solution] "The solution is for the service that sends the message to first store the message in the database as part of the transaction that updates the business entities."
[§Solution — message relay] "A separate process then sends the messages to the message broker."
[§Resulting context — benefits] "Messages are guaranteed to be sent if and only if the database transaction commits"
[§Resulting context — drawbacks] "Potentially error prone since the developer might forget to publish the message/event after updating the database."
Claims Extracted / 추출된 주장
| Claim ID | Claim | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| MSIO-OUTBOX-C1 | service command 는 DB aggregate 변경 + 메시지 브로커로의 메시지 발행 두 가지를 함께 해야 하는 경우가 일반적 (dual-write 컨텍스트) | [§Context] "A service command typically needs to create/update/delete aggregates in the database and send messages/events to a message broker." | engineering-blog |
event-driven / SOA / microservices 의 command 흐름 | 모든 service command 가 메시지 발행을 동반해야 한다는 강제는 아님 — typically (일반적) |
| MSIO-OUTBOX-C2 | DB update 와 메시지 발행이 atomic 하지 않으면 data inconsistency / bug 가 발생할 수 있음 | [§Context] "The command must atomically update the database and send messages in order to avoid data inconsistencies and bugs." | engineering-blog |
DB commit 과 broker publish 가 별개 트랜잭션인 모든 시나리오 | 어떤 종류의 inconsistency 가 어떤 빈도로 발생하는지의 정량적 근거는 본 인용에 없음 |
| MSIO-OUTBOX-C3 | 핵심 문제는 "DB 와 메시지 브로커를 어떻게 atomic 하게 동시에 update 할 것인가" | [§Problem] "How to atomically update the database and send messages to a message broker?" | engineering-blog |
dual-write 문제 정의 | 2PC (XA) 같은 distributed transaction 이 부적절하다는 결론은 본 한 줄 인용으로 직접 입증 안 됨 — Forces 섹션과 결합 필요 |
| MSIO-OUTBOX-C4 | force: 메시지는 service 가 발행한 순서대로 브로커에 전달되어야 함 | [§Forces] "Messages must be sent to the message broker in the order they were sent by the service." | engineering-blog |
순서 보장이 필요한 도메인 이벤트 (state machine 등) | 모든 메시징 시나리오가 strict ordering 을 요구한다는 의미는 아님 — 본 force 가 적용되는 시스템에서만 |
| MSIO-OUTBOX-C5 | 해법: 발행할 메시지를 business entity 를 update 하는 동일 트랜잭션의 일부로 DB 에 먼저 저장 | [§Solution] "The solution is for the service that sends the message to first store the message in the database as part of the transaction that updates the business entities." | engineering-blog |
OUTBOX 테이블 구현 시 | 메시지 저장 테이블이 반드시 "OUTBOX" 라는 이름이어야 한다는 강제는 아님 (관습일 뿐) |
| MSIO-OUTBOX-C6 | 별도 process (message relay) 가 저장된 메시지를 브로커로 발행 | [§Solution] "A separate process then sends the messages to the message broker." | engineering-blog |
polling publisher / transaction log tailing 등 relay 구현 | relay 가 별도 OS 프로세스여야 한다는 강제는 아님 — 동일 서비스 내 별도 스레드/스케줄러도 일반적 |
| MSIO-OUTBOX-C7 | benefit: 메시지는 DB 트랜잭션이 commit 된 경우에 한해 그리고 그 경우에만 발행이 보장됨 (if and only if) | [§Resulting context — benefits] "Messages are guaranteed to be sent if and only if the database transaction commits" | engineering-blog |
at-least-once delivery + 일관성 보장 평가 | exactly-once 까지 보장된다는 의미는 아님 — relay 가 동일 메시지를 재발행할 수 있으므로 consumer 측 idempotency 필요 |
| MSIO-OUTBOX-C8 | drawback: 개발자가 DB update 후 메시지/이벤트 발행을 잊을 수 있어 error-prone | [§Resulting context — drawbacks] "Potentially error prone since the developer might forget to publish the message/event after updating the database." | engineering-blog |
outbox write 가 application code 의 명시적 호출에 의존하는 구현 | 모든 outbox 구현이 error-prone 하다는 의미는 아님 — 도메인 이벤트 자동 수집 (e.g., Spring Data domain events / aspect) 으로 완화 가능 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
MSIO-OUTBOX-C1~C3: dual-write 문제의 정의 + atomicity 요구MSIO-OUTBOX-C4: ordering forceMSIO-OUTBOX-C5~C6: 해법의 두 축 (OUTBOX 저장 + 별도 relay)MSIO-OUTBOX-C7~C8: benefit (commit 과 발행의 if-and-only-if 보장) 과 drawback (forget-to-publish)
- 이 자료가 증명하지 않는 것:
- 본 페이지가 공식 vendor doc 이라는 점 — microservices.io 는 Chris Richardson 의 personal pattern catalog. AWS/Spring/Confluent 등의 공식 채택을 의미하지 않음. strength
engineering-blog. - 특정 구현 (Debezium / Spring Modulith / Eventuate / 자체 polling) 이 정답이라는 결론
- 메시지 브로커가 반드시 Kafka 여야 한다는 점 (RabbitMQ / SQS / Pulsar 모두 동일 패턴 적용 가능)
- exactly-once delivery 보장 —
C7의 "if and only if" 는 DB-쪽 보장이며, consumer 측 idempotency 와 독립 - outbox 테이블 schema 의 정확한 컬럼 구성 (id, aggregate_id, type, payload, created_at 등은 관습)
- 본 페이지가 공식 vendor doc 이라는 점 — microservices.io 는 Chris Richardson 의 personal pattern catalog. AWS/Spring/Confluent 등의 공식 채택을 의미하지 않음. strength
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-tmpl 이 polling publisher / transaction log tailing 중 어느 변형을 default 로 채택할지 (raw/branch-notes/feature-domain-event-outbox-contract)
- 도메인 이벤트 수집 메커니즘 (Aggregate.registerEvent → Repository.save 시 함께 outbox insert) 의 구체 설계
- consumer 측 idempotency 보장 정책
메모 / Notes
- 본 패턴은 Microservices Patterns (Chris Richardson, Manning 2018) 책에도 동일 내용 수록. 책이 더 상세하지만 본 페이지가 가장 자주 인용되는 단일 URL.
- microservices.io 가 personal blog 임에도 패턴 카탈로그로서 사실상 표준 참조로 사용되는 경우가 많음. 그러나 본 wiki 의 strength 분류 기준에서는
engineering-blog가 정확 — 공식 vendor doc / 표준이 아니므로. - "공식 best practice" 로 인용하려면 동일 패턴을 다루는 official-vendor-doc (예: AWS Prescriptive Guidance, Microsoft Cloud Design Patterns) 와 corroborate 해야 함.
Related / 관련
- 같은 주제 다른 raw:
- raw/official-docs/cqrs-fowler-bliki (CQRS 와 자주 결합되는 패턴 — Fowler bliki)
- raw/official-docs/arch-hexagonal-cockburn (event publishing port 정의 기반)
- 이 자료를 인용하는 branch:
- 인용하는 project:
- 이 자료를 인용한 wiki 요약: (미작성)