면책 조항. 이 글은 Stripe의 공개 커뮤니케이션 — 엔지니어링 블로그, 컨퍼런스 발표, 오픈소스 저장소, 외부 케이스 스터디 — 만을 기반으로 합니다. Stripe 공식 아키텍처 문서가 아닙니다. 복잡한 스택이 C4 모델로 어떻게 readable해질 수 있는지 보여주기 위해 공개된 내용을 모델링합니다. 세부사항이 Stripe가 명시한 것이 아니라 추론된 경우 그 사실을 명시합니다.
Charge의 해부학: Stripe를 C4로 Archyl에서 모델링하기
POST 요청이 블랙 프라이데이 태평양 시간 새벽 3시에 Stripe에 도달합니다. 20초 후, 머천트가 입금되었고, cardholder의 발행 은행이 charge를 승인했고, 자금은 settlement 큐에 들어갔고, 머천트의 서버는 서명된 webhook을 받았으며, Stripe의 리스크 엔진은 100ms 이내에 트랜잭션을 점수 매겼습니다.
그 단일 요청은 BFCM 2024 피크에서 초당 27,395번 반복되며, 14개의 Stripe 시스템과 최소 4개의 외부 네트워크를 frame zero가 머천트의 대시보드에 도달하기 전에 가로지릅니다.
2025년에 Stripe는 이 스택을 통해 1.9조 달러 를 처리했고, 블랙 프라이데이 동안 99.9999% 가동시간 을 유지했습니다 — 6개의 9, 연간 32초의 가동 중단에 해당합니다. 그들은 이를 자체 제작한 타입 시스템으로 type-checked된 약 1,500만 줄의 Ruby에서 했습니다.
인터넷 절반의 신용카드 결제를 운영하는 스택을 어떻게 이해할까요? Netflix처럼, 한 번에는 이해할 수 없습니다. 그것이 바로 C4 모델이 해결하기 위해 발명된 문제입니다.
이 글에서는 한 가지 사용자 액션 — stripe.PaymentIntents.create() 호출 — 을 따라가며, 그것이 4개의 C4 레벨에 걸쳐 Stripe의 아키텍처를 가로지르는 것을 봅니다. 모든 제품을 다루지는 않습니다. 하나의 charge를 추적하고, 그 길에 만나는 선택을 설명하는 ADR을 작성하며, 각 박스를 소유한 팀의 맵으로 끝맺습니다.
레벨 1 — System Context: 15개 제품, 1조 달러

System Context 레벨에서 Stripe는 "결제 API"가 아닙니다. 기반을 공유하는 15개의 별개의 제품 시스템입니다:
- Payments — 역사적 핵심: charges, payment intents, refunds, payouts
- Connect — 다자간 결제, 마켓플레이스, 플랫폼
- Billing — 구독, 청구서, 사용량 기반 청구
- Atlas — Delaware C-Corp/LLC 법인 설립
- Capital — 머천트 대출
- Issuing — 가상 및 물리 카드 생성
- Treasury — banking-as-a-service (Goldman Sachs 파트너십)
- Identity — KYC/KYB 검증
- Tax — 판매세, VAT, GST
- Climate — 트랜잭션당 탄소 상쇄
- Radar — ML 사기 탐지 (100ms 이하 스코어링)
- Sigma — Stripe 데이터에 대한 SQL 분석
- Terminal — POS 하드웨어
- Financial Connections — 은행 계좌 연결 (그들의 Plaid)
- Apps Marketplace — Dashboard의 서드파티 앱
주변에는: 머천트, cardholder, 4개의 카드 네트워크(Visa, Mastercard, Amex, Discover) 및 지역 네트워크(JCB, UnionPay), 100개 이상의 대체 결제 방법(Apple Pay, Klarna, ACH, SEPA, iDEAL...), acquiring 및 issuing 은행, 은행 파트너(Goldman Sachs, Evolve, Cross River), 세무 당국, 신원 제공자, 그리고 기반 클라우드인 AWS(모노 클라우드).
15개 시스템, 8가지 카테고리의 외부 액터. 나머지는 모두 디테일입니다.
이것이 레벨 1의 선물입니다: System Context에서는 Payments가 20개의 마이크로서비스라는 것을 알 필요가 없습니다. 그것이 존재하고, card networks와 통신하고, Connect가 Treasury와 조정하고, AWS가 모든 것을 떠받친다는 것을 알면 됩니다. 다이어그램은 대화의 시작점이지 인벤토리가 아닙니다.
ADR-001 · 1일차부터 API에 Idempotency keys 통합
상태 · Accepted (2011년, 2026년에도 여전히 활성)
컨텍스트 · 네트워크는 신뢰할 수 없습니다. 실패한 POST /charges 를 재시도하는 머천트는 고객에게 이중 청구할 수 있습니다. 2011년 업계의 답은 "머천트가 그것을 처리해야 한다" 였습니다 — 분산 시스템 복잡성을 모든 API 컨슈머에게 밀어내는 것.
결정 · 모든 mutating API 호출에 Idempotency-Key 를 요구한다. 키, 요청 해시, 응답을 저장한다. 재시도 시 키가 일치하면 저장된 응답을 replay한다. 옵트인이 아닌 API의 first-class 부분으로 출시한다.
결과 · Stripe의 idempotency 모델은 사실상 업계 표준이 되었습니다. IETF의 Idempotency-Key 드래프트는 그것에서 직접 영감을 받았습니다. 모든 Stripe API 사용자는 알든 모르든 POST /charges 를 안전하게 재시도 가능한 작업으로 만드는 계약의 혜택을 받습니다. 어떻게 작동하는지는 레벨 3에서 줌인하겠습니다.
이는 Stripe의 API 표면을 가장 강력하게 형성하는 단일 아키텍처 선택입니다. 그것 없이는 C4 모델은 모든 mutating boundary에 retry 로직을 노출해야 했을 것입니다 — 모든 컨슈머에게 분산 시스템 복잡성을 누출시킵니다.
Archyl에서는 ADR이 이렇게 자기 자리를 얻습니다: 왜 boundary가 그렇게 보이는지를 설명 하는 것입니다.
레벨 2 — Container: Payments core 줌인

머천트의 stripe.PaymentIntents.create() 가 Payments의 가장자리에 도착합니다. 박스를 열어봅시다.
Payments 내부에서 공개 소스는 적어도 다음 컨테이너들을 드러냅니다:
- Apiori — API 게이트웨이. 원래 Ruby + Rails이지만, hot-path 코드는 auth 및 라우팅 레이어에서 sub-150 µs 지연을 위해 점진적으로 Go로 재작성됨.
- Idempotency layer — 모든 mutating 엔드포인트 앞에 앉는 cross-cutting concern. row-level locking을 사용하는 PostgreSQL이 백업.
- PaymentIntent service — 상태 머신을 오케스트레이션:
requires_payment_method→requires_confirmation→requires_action(3DS 챌린지) →processing→succeeded(또는requires_capture). - Card Data Vault — 물리적으로 격리된 PCI 환경, AES-256 at rest, 메인 서비스는 PAN을 복호화할 수 없음. 모든 카드 데이터는 토큰화를 거침.
- Radar — 100ms p99 미만 사기 스코어링. 2022년부터 순수 DNN, ResNeXt에서 영감을 받은 아키텍처.
- Network connectors — Visa, Mastercard, Amex 등을 위한 어댑터. 와이어상에서 ISO 8583과 독점 프로토콜을 사용.
- Webhook delivery service — at-least-once 전달, 3일에 걸쳐 16번 재시도, exponential backoff, HMAC-SHA256 서명.
- Ledger — 불변 이벤트 로그, 일일 ~50억 이벤트, 결제당 ~100 ledger 엔트리. 조정, 감사, 회계의 source of truth.
- DocDB — Stripe의 자체 Database-as-a-Service, MongoDB 위에 구축. 초당 500만 쿼리, 5,000개 이상의 컬렉션, 2,000개 이상의 샤드, 페타바이트의 금융 데이터.
이 레벨의 기술 스택: 지배적 언어인 Sorbet 타입의 Ruby (1,500만 줄), hot path에 Go, 관계형 concern (idempotency, accounts)에 PostgreSQL, 고볼륨 document 워크로드에 DocDB, 이벤트에 Apache Kafka, 실시간 분석에 Apache Pinot, 스트림 처리에 Apache Flink.
전형적인 charge는 Apiori → Idempotency layer → PaymentIntent service → (토큰을 위한 Vault) → (위험을 위한 Radar 병렬) → Network connector → Ledger → Webhook fanout을 거칩니다. 이 모든 것을, retry와 함께, Veneur를 통해 end-to-end 계측되고, 외부 egress에는 Smokescreen을 통해 안전하게 라우팅됩니다.
ADR-002 · DocDB — 재작성 대신 MongoDB 위에 구축
상태 · Accepted (~2018년, 지속 투자)
컨텍스트 · 2018년까지 Stripe의 MongoDB 데이터 볼륨은 기성 제품을 압박하고 있었습니다: 페타바이트 컬렉션의 스키마 마이그레이션은 위험했고, 샤딩은 운영 부담이었으며, 99.999% 가동시간 요구사항은 유지보수 윈도우를 허용하지 않았습니다. 업계는 "관계형 스토어로 재작성하라" 고 말했을 것입니다.
결정 · 데이터 레이어를 다른 엔진으로 마이그레이션하지 않는다. 대신 MongoDB 위에 자체 Database-as-a-Service를 구축한다: Database Proxy, Chunk Metadata Service, dual-write/backfill/dual-read/cleanup 패턴을 관리되는 프리미티브로 실행하는 Data Movement Platform, 그리고 아웃바운드 이벤트를 위한 CDC 서비스.
결과 · Stripe는 MongoDB의 유연한 document 모델의 장점에 더해 관리되는 플랫폼의 운영 보장을 얻습니다: 5M QPS, 99.999% 정상 상태 가동시간, 일상적인 작업으로서의 zero-downtime 마이그레이션. 인터넷 루머가 가끔 주장하는 "Mongo → DynamoDB" 마이그레이션? 일어난 적이 없습니다. 그들은 대신 두 배로 베팅했습니다.
이 ADR은 path-dependent 아키텍처 의 훌륭한 예입니다: 2018년의 정답은 교체가 아닌 확장이었습니다.
레벨 3 — Component: Idempotency layer 내부

Stripe 스택의 모든 컴포넌트 중에서 Idempotency layer는 가장 공개적으로 문서화된 것입니다 — 2017년 Brandur Leach의 포스트는 분산 시스템 엔지니어들에게 여전히 정전과 같은 참고 자료입니다.
idempotency key가 있는 단일 POST /charges 는 레이어 내부의 이러한 컴포넌트들을 가로지릅니다:
- Request hasher — 요청 페이로드의 결정론적 해시를 계산. 동일한 idempotency key가 다른 페이로드와 함께 도착하면 API는 422를 반환 (클라이언트가 프로그래밍 실수를 했음).
- Idempotency key store —
(account_id, idempotency_key)를 키로 하는 PostgreSQL 테이블.request_hash,response_code,response_body,recovery_point,last_run_at,locked_at포함.locked_at컬럼은 동시 재시도를 위한 row-level locking을 구현. - Phase executor — 작업을 foreign state mutations 로 분리된 원자적 단계로 분할. 각 단계는 순수하게 로컬(Postgres-only, idempotency row와 트랜잭션) 또는 하나의 외부 side-effect (Vault tokenize, 네트워크 charge, webhook 전송) 중 하나.
- Recovery point tracker — 현재 단계 지속화:
started→ran_charge→wrote_ledger→enqueued_webhook→finished. 재시도 시 executor는 recovery point에서 재개. - Job enqueuer — 비동기 side-effects (이메일, webhooks)를 위해 recovery point 업데이트와 동일한 Postgres 트랜잭션 에 영구 작업을 큐잉. 구조적으로 원자적.
- Background runner — 자체 retry 시맨틱, exponential backoff, dead-letter store로 작업 큐를 비웁니다.
패턴은 보면 잔인할 정도로 단순합니다: 모든 로컬 변경은 idempotency 행 업데이트와 동일한 Postgres 트랜잭션에 살고, 모든 외부 변경은 두 개의 recovery point 사이에 산다. 이 형태는 이 프리미티브 없이 구축된 분산 시스템을 괴롭히는 이중 쓰기 버그의 전체 클래스를 제거합니다.
이것이 Component 레벨 C4가 어떻게 보이는지입니다: "여기 코드가 있어요" 가 아니라 "여기 비즈니스적으로 의미 있는 프리미티브의 체인이 있고, 각각이 owned되고, 각각이 교체 가능하고, 각각이 측정 가능" 입니다.
ADR-003 · Sorbet — 타입 체커에 투자, Ruby 재작성 안 함
상태 · Accepted (~2017년, 2019년 오픈소스화, 여전히 기본)
컨텍스트 · 2017년까지 Stripe의 Ruby + Rails 모놀리스는 1,000만 줄을 넘어섰습니다. 그 규모의 핀테크에 대한 업계의 지배적 조언은 타입 언어로 재작성 — Java, Go 또는 Scala — 였습니다. 추정 비용은 수년과 수백 명의 엔지니어였습니다. 한편 Ruby DX는 빠르게 출시하기 위한 Stripe의 경쟁 우위였습니다.
결정 · 재작성하지 않는다. Ruby용 점진적 타입 체커를 구축한다. 18개월과 작은 팀을 들여 수백만 줄로 확장되는 멀티스레드, IDE급 타입 시스템을 출시한다. 오픈소스화한다.
결과 · Sorbet은 이제 sub-second 증분 지연으로 1,500만 줄의 Stripe Ruby를 type-check합니다. Stripe는 재작성 세금을 한 번도 내지 않았습니다. 그들은 type-checker 발명 세금 을 — 한 번 — 냈습니다. Sorbet은 Coinbase, Shopify, GitHub 등이 사용하는 의미 있는 오픈소스 프로젝트가 되었습니다.
Archyl 모델에서는 이런 ADR이 아키텍처와 함께 여행합니다. 2026년에 Apiori 컨테이너를 클릭하고 "Ruby + Sorbet"을 볼 때, 왜 Java가 아닌지를 설명하는 2017년의 결정도 보게 됩니다.

세 가지 결정. Archyl의 세 카드, 각각이 형성하는 C4 요소에 링크 — Idempotency keys는 모든 mutating 엔드포인트에, DocDB는 데이터 레이어에, Sorbet은 모든 Ruby 컨테이너에. 다이어그램은 현재형; ADR은 그 이유.
Ownership: 모델을 책임감으로 변환

C4 모델은 팀을 매핑하기 전까지는 정적인 아티팩트입니다.
Stripe는 엔지니어링 구조에 대해 공개적으로 소통합니다: 강력한 Foundations 그룹 (Infrastructure, Security, Data Platform, Developer Experience), 각 주요 시스템에 정렬된 제품 팀들 (Payment Methods, Connect, Capital, Identity, Issuing, Treasury, Climate, Radar), 그리고 ML과 observability를 위한 횡단 그룹들.
이들을 C4 모델에 떨어뜨리면:
- Foundations 가 Apiori, Sorbet, Veneur, Smokescreen, Kubernetes 플랫폼, DocDB, Card Data Vault를 소유 — 모든 제품이 구축되는 기반
- Payment Methods 가 Network connectors, PaymentIntent state machine, 메소드별 서비스 (카드, ACH, SEPA, 지갑)를 소유
- Connect 가 Account 서비스, capability gating, 다자간 자금 흐름, payout을 소유
- Capital 이 대출 결정 파이프라인과 머천트의 Stripe Payments 이력과의 통합을 소유
- Identity 가 KYC/KYB 워크플로우와 Connect 온보딩의 컨플라이언스 게이팅을 소유
- Radar (ML 팀)가 사기 DNN, 모델 서빙, 트레이닝 파이프라인을 소유
- Issuing & Treasury 가 은행 파트너 통합과 카드 라이프사이클을 소유
- Climate 가 탄소 오프셋 마켓플레이스 통합을 소유
이 매핑은 장식이 아닙니다. 그 후에 오는 모든 것의 기반입니다.
시스템, 컨테이너 또는 컴포넌트에 팀 소유자가 있으면, drift 탐지가 책임 있는 것이 됩니다: 새 서비스가 커밋에 나타나고 다이어그램에 없으면 특정 팀이 호출됩니다. 컨포먼스 규칙이 위반되면 (예: Foundations가 아닌 서비스가 Card Data Vault에서 직접 읽으려 시도) inbox에 이름이 있습니다.
Archyl에서 Ownership Map은 문서화 도구가 거버넌스 도구가 되는 순간입니다.
Drift, 컨포먼스, 그리고 주간 다이제스트
이 크기의 모델은 drift합니다. 새 제품이 도착합니다 — 2022년 Climate, Treasury, Tax 확장, Apps Marketplace. 스택이 변합니다 — Apiori 경로가 Go로 마이그레이션, Pinot이 더 오래된 분석을 대체, Sorbet strictness 상승.
Archyl은 주간 drift 점수를 계산합니다: 문서화된 C4 모델과 현재 코드에 있는 것 사이의 격차. 컨포먼스 규칙은 정책 레이어를 추가합니다 — "모든 컨테이너는 소유자 팀이 필요", "Foundations 서비스만 Card Data Vault를 읽을 수 있음", "모든 공개 API 변경은 versioning ADR을 참조해야 함".
Stripe에게 이는 1,500만 줄과 초당 27,000 요청 규모에서의 drift 탐지입니다. 하지만 규칙은 10개 서비스일 때와 동일합니다.
그리고 최근 출시한 팀 아키텍처 다이제스트는 Stripe 같은 설정에서:
- Foundations 의 월요일 다이제스트는 Apiori, Vault, DocDB, K8s 플랫폼을 커버
- Payment Methods 의 다이제스트는 Network connectors, PaymentIntent service, 각 메소드별 통합을 커버
- Radar 의 다이제스트는 사기 DNN, 트레이닝 파이프라인, 모델 롤아웃을 커버
- 각 다이제스트는 자기 팀이 소유한 경계에 스코프됨
같은 표면. 다른 스코프. 그것이 C4 + ownership이 잠금 해제하는 대칭성입니다.
1조 달러를 처리할 필요가 없습니다
당신은 Stripe가 아닙니다. 대부분의 엔지니어링 조직은 그렇지 않습니다.
하지만 교훈은 아래로도 스케일합니다. Context를 Container와 Component에서 분리하는 규율, path-dependent한 결정을 설명하는 ADR을 작성하는 규율 (우리는 Mongo 위에 구축했다, 재작성 대신 Ruby type-check했다), 모든 박스에 ownership을 첨부하는 규율 — 그 규율이 50개 서비스 스택이 1,500만 줄처럼 느껴지지 않게 하는 것입니다.
C4 + ADR + Ownership + Drift + 컨포먼스가 Archyl이 out of the box로 제공하는 것입니다. Stripe 예시는 금융 시스템 도메인에서 모델의 가장 큰 그럴듯한 스트레스 테스트일 뿐입니다.
자신의 아키텍처를 열어보세요. 15개의 제품을 스케치하세요 (또는 3개라면 3개로). 가장 놀라운 과거 결정을 가진 것을 골라 그 컨테이너로 줌인하세요. 신참을 어리둥절하게 할 만한 것을 설명하는 3개의 ADR을 작성하세요. 각 컨테이너에 팀을 매핑하세요.
대부분의 엔지니어링 조직이 1년에 도달하는 곳보다 앞서 있을 것입니다.
자신의 아키텍처를 C4로 모델링하고 싶으신가요? Archyl로 시작하세요. 왜 ADR과 C4가 함께 더 잘 작동하는지 또는 Architecture Change Requests가 C4 모델에 풀 리퀘스트의 엄격함을 가져오는 방법도 읽어보세요. 이전 케이스 스터디는 Netflix in C4 — Anatomy of a Play를 모델링했습니다.