Hybrid OrderBook System
On + Off Chain 기반 탈중앙화 하이브리드 오더북 시스템Decentralized hybrid orderbook engine based on On + Off Chain
1. 프로젝트 개요1. Project Overview
현재 개발중인 프로젝트로, 공개 가능한 범위 내에서 제가 담당한 핵심 모듈인 Hybrid OrderBook System에 대한 내용을 다룹니다.This is a confidential project currently under development. While the project name and specific details cannot be disclosed, this portfolio covers the Hybrid OrderBook System, the core module I am responsible for, within the scope that can be shared.
Off-Chain에서 고속 매칭을 수행하고, On-Chain에서 정산의 투명성과 최종성을 보장하는 2-Layer 하이브리드 구조입니다.It is a hybrid 2-layer architecture that performs high-speed matching off-chain while guaranteeing settlement transparency and finality on-chain.
| 항목Item | 내용Details |
|---|---|
| 프로젝트명Project | Hybrid OrderBook System |
| 분류Category | On + Off Chain 기반 탈중앙화 하이브리드 오더북 시스템Decentralized hybrid orderbook engine based on On + Off Chain |
| 개발 기간Period | 2025.10 ~ (개발 진행 중)Oct 2025 ~ (In Development) |
| 역할Role | Backend DeveloperBackend Developer (System Design, OrderBook Engine, Concurrency Control, Infrastructure) |
2. 프로젝트 배경과 기술 스택2. Background and Tech Stack
순수 On-Chain 오더북은 가스비 부담과 블록 컨펌 지연으로 인해 거래소 수준의 매칭 속도를 달성할 수 없었다. 이를 해결하기 위해 Off-Chain에서 고속 매칭을 수행하고, 정산만 On-Chain에서 처리하는 2-Layer 하이브리드 구조를 설계했다.Pure on-chain orderbooks couldn't achieve exchange-level matching speed due to gas cost burden and block confirmation delays. To solve this, a hybrid 2-layer architecture was designed to perform high-speed matching off-chain while processing only settlement on-chain.
| 분류Category | 기술Technologies |
|---|---|
| Language / Framework | Python, FastAPI |
| Database | MongoDB Atlas (Event Store + View + Outbox) |
| Infrastructure | AWS EKS / Karpenter & HPA / Docker + ECR / GitHub Actions / SQS FIFO / API Gateway |
| Messaging | Transactional Outbox Pattern / SQS FIFO (Relay + Worker) |
| Architecture | DDD + Hexagonal Architecture / Event Sourcing / CQRS / Transactional Outbox |
| Observability | Prometheus / Fluent Bit / Grafana / AWS OpenSearch |
기술 선택과 근거Technology Choices and Rationale
| 기술Technology | 선택 근거Rationale |
|---|---|
| SQS FIFO | 마켓별 주문 순서 보장이 필수. AWS 완전 관리형으로 운영 복잡도를 최소화하고, 금융 시스템 특성상 단순함과 안정성을 중시Market-level order sequencing essential. AWS fully managed service minimizes operational complexity; financial system prioritizes simplicity and stability |
| MongoDB (Event Store) | Append-Only 이벤트 저장에 Document 모델이 적합. RDBMS 대비 스키마 유연성이 높아 이벤트 타입별 다양한 payload 구조 대응 용이Document model suited for Append-Only event storage. Higher schema flexibility than PostgreSQL for diverse payload structures per event type |
| Transactional Outbox | 온체인과 오프체인 간 2-Phase 기록 방식은 데이터 정합성을 보장하기 어려워, 온체인 트랜잭션 발행과 DB 쓰기의 원자성을 Outbox 패턴으로 해결2-Phase recording between on-chain and off-chain makes data consistency difficult to guarantee, so Outbox pattern ensures atomicity of on-chain transaction publishing and DB writes |
| Roll-Forward | 금융 원장의 Append-Only 원칙 유지. Rollback은 기존 레코드를 수정하여 감사 추적성을 해치므로, Roll-Forward의 보상 이벤트 추가 방식 채택Preserves financial ledger Append-Only principle. Rollback modifies existing records breaking audit trail; adopted Roll-Forward compensating event approach |
| Event Sourcing + CQRS | 모든 상태 변경을 Append-Only 이벤트로 기록하여 완전한 감사 추적성(Audit Trail) 확보. 조회 전용 데이터는 View Store로 Projection하여 Command / Query 부하를 분리, 각각 독립적으로 스케일링Records all state changes as Append-Only events for complete audit trail. Read-optimized data projected to View Store, separating Command / Query loads for independent scaling |
| DDD + Hexagonal | 금융 서비스 특성상 시스템 안정성과 도메인 순수성이 최우선. Domain(Port 포함) / Service / Entrypoints / Adaptors 계층 분리로 Smart Contract 교체, DB 변경 등 외부 서비스 등의 변경이 실제 비즈니스 도메인 로직에 영향을 주지 않는 유연한 구조 확보System stability and domain purity are paramount for financial services. Layered separation (Domain / Service / Entrypoints / Adaptors) ensures infrastructure-level changes like Smart Contract replacement or DB migration do not affect domain logic |
3. 핵심 기술 구현3. Core Technical Implementation
3-1. Hybrid 2-Layer 구조 & 3-Queue 메시지 아키텍처3-1. Hybrid 2-Layer Structure & 3-Queue Message Architecture
서비스의 핵심인 주문 매칭 엔진을 Hybrid OrderBook 구조로 설계했다. Off-Chain에서 주문 매칭과 원장 관리를 수행하고 On-Chain에서 최종 정산(Settlement)을 확정하는 2-Layer 구조이다.The order matching engine was designed as a Hybrid OrderBook — a 2-Layer structure where Off-Chain handles order matching and ledger management while On-Chain confirms final settlement.
- Off-Chain (OrderBook Core): 주문 접수, 매칭, Fund Lock, 원장 기록 (빠른 응답과 복잡한 비즈니스 로직 처리)Off-Chain (OrderBook Core): Order intake, matching, Fund Lock, ledger recording (fast response and complex business logic)
- On-Chain (Smart Contract): 정산 확정, 자산 이동 (블록체인의 불변성과 투명성 보장)On-Chain (Smart Contract): Settlement confirmation, asset transfer (blockchain immutability and transparency)
온체인 트랜잭션은 2-of-2 서명(사용자 서명 + 오퍼레이터 지갑 서명)이 필요하며, 오퍼레이터별 논스(Nonce) 충돌 방지를 위해 역할별로 큐를 분리하고 논스를 직접 관리한다.On-chain transactions require 2-of-2 signing (user signature + operator wallet signature), and queues are separated by role with direct nonce management to prevent per-operator nonce conflicts.
| Queue | 유형Type | 역할Role |
|---|---|---|
| Market Queue | 오프체인 전용Off-chain only | 마켓별 주문 순차 처리 (SQS FIFO market:{market_id} GroupId)Per-market order sequential processing (SQS FIFO market:{market_id} GroupId) |
| Admin Operator Queue | 온체인 전용On-chain only | Market 생성 등 시스템 관리자 기능 및 이벤트 제어System admin functions (market creation) and event control |
| Settlement Operator Queue | 온체인 전용On-chain only | 매칭 체결 → 온체인 정산 Task 처리Matched trade → on-chain settlement task processing |
- 2-of-2 서명: 사용자 서명과 오퍼레이터 지갑 서명이 합쳐져야 온체인 트랜잭션이 실행됨 (단독 서명으로는 자산 이동 불가)2-of-2 signing: Both user signature and operator wallet signature must be combined for on-chain transaction execution (asset movement impossible with a single signature)
- 논스 직접 관리: 오퍼레이터별로 큐를 분리하여 동시 트랜잭션 시 논스 충돌을 방지하고, 논스 시퀀스를 직접 관리하여 트랜잭션 순서 보장Direct nonce management: Queues separated per operator to prevent nonce conflicts during concurrent transactions, with direct nonce sequence management ensuring transaction ordering
- 논스 복구 메커니즘: 특정 논스의 트랜잭션이 무한 펜딩 상태이거나 논스가 겹치는 경우, 해당 논스에 제로 서명(빈 서명)을 제출하여 논스를 강제 소비 처리 → 이후 트랜잭션이 정상적으로 진행되도록 복구Nonce recovery mechanism: When a nonce transaction is stuck in infinite pending or nonce collision occurs, submit a zero signature (empty signature) to force-consume the nonce → enabling subsequent transactions to proceed normally
3-2. 주문 처리 파이프라인3-2. Order Processing Pipeline
주문 처리의 각 단계(Placed, Matched, Settlement, Cancelled)에서 발생하는 모든 DB 변경은 Unit of Work 패턴을 적용하여 MongoDB Transaction으로 원자적 커밋한다. 비즈니스 데이터 변경과 Outbox Event 기록을 하나의 트랜잭션으로 묶어, 중간 실패 시 전체 롤백되므로 부분 커밋에 의한 데이터 불일치를 원천 방지한다.All DB changes across each stage (Placed, Matched, Settlement, Cancelled) are atomically committed via MongoDB Transaction using the Unit of Work pattern. Business data changes and Outbox Event records are bundled in a single transaction — on mid-failure, full rollback prevents data inconsistency from partial commits.
Placed (주문 등록)Placed (Order Registration)
유효성 검증(잔액, 가격 / 수량 범위, 마켓 상태) 후 주문 금액만큼 available → pending으로 Fund Lock(MongoDB Unique Index 활용)을 수행한다.After validation (balance, price / quantity range, market status), Fund Lock (using MongoDB Unique Index) moves order amount from available → pending.
Matched (매칭)Matched
가격-시간 우선 원칙(Price-Time Priority)에 따라 매칭한다. BUY는 높은 가격 우선, SELL은 낮은 가격 우선이며, 동일 가격 시 먼저 등록된 주문이 우선한다.Matching follows Price-Time Priority. BUY prioritizes highest price, SELL prioritizes lowest price, with earliest order first at same price.
- 매칭 성능을 위한 인덱스 전략:
{market_id, side, price, created_at}복합 인덱스로 오더북 스캔을 최적화하여, 대량 미체결 주문에서도 최적의 상대 주문을 빠르게 탐색Index strategy for matching performance: Compound index{market_id, side, price, created_at}optimizes orderbook scans, enabling fast counterparty discovery even with large volumes of unfilled orders - Partial Fill 처리: 부분 체결 시 잔여 수량을 오더북에 유지하고, 체결된 부분만 Settlement으로 전달 — 주문 상태를
PLACED → PARTIAL → FILLED로 전이Partial Fill handling: Remaining quantity stays in orderbook on partial fills, only filled portion proceeds to Settlement — order status transitionsPLACED → PARTIAL → FILLED
Settlement (정산)Settlement
매칭 확정 후 Off-Chain 원장과 On-Chain 정산을 동기화하는 핵심 파이프라인이다. 3-Queue 메시지 아키텍처(섹션 3-1)의 Settlement Operator Queue를 통해 온체인 정산을 처리한다.The core pipeline synchronizing Off-Chain ledger and On-Chain settlement after matching. On-chain settlement is processed via the Settlement Operator Queue from the 3-Queue message architecture (Section 3-1).
- Market Queue에서 매칭 엔진 실행 → 체결 결과를 in-memory에 보관Market Queue executes matching engine → holds matched results in-memory
- Outbox Event Message를 DB에 저장Saves Outbox Event Message to DB
- Outbox Relay가 감지 → Settlement Operator Queue에 온체인 정산 Task 발행Outbox Relay detects → publishes on-chain settlement Task to Settlement Operator Queue
- 매칭 엔진은 동시에 DB 커밋할 정보를 메모리에서 정리Matching engine simultaneously organizes commit data in memory
- DB 커밋 직전에 Outbox Event의 온체인 결과를 폴링 (BSC 기준 최대 30초 타임아웃)Polls on-chain result of Outbox Event before DB commit (BSC-based max 30-second timeout)
- 온체인 성공 확인 후 → 오프체인 매칭 체결 DB 커밋 진행. 30초 이상 폴링 실패 시 DB 커밋 없이 종료하여 매칭 취소 처리After on-chain success confirmation → proceeds with off-chain matching DB commit. If polling fails beyond 30 seconds, terminates without DB commit → match cancelled
- Transactional Outbox 패턴: Settlement Intent와 Outbox Event를 하나의 DB 트랜잭션으로 원자적 커밋하여, 정산 이벤트 유실을 원천 차단 (섹션 3-4 상세)Transactional Outbox pattern: Settlement Intent and Outbox Event atomically committed in a single DB transaction, eliminating settlement event loss (see Section 3-4)
Failure Recovery — Roll-Forward 전략Failure Recovery — Roll-Forward Strategy
금융 시스템에서 가장 중요한 원칙인 원장 불변성(Append-Only)을 유지하면서 장애를 복구하기 위해, Rollback이 아닌 Roll-Forward 방식을 채택했다.To recover from failures while preserving the most critical principle in financial systems — ledger immutability (Append-Only) — a Roll-Forward approach was adopted instead of Rollback.
Rollback 방식 (미채택):Rollback approach (not adopted):
100(잔액) → 20(출금) → 80(잔액) → 실패 → [기존 레코드 수정] → 100(잔액)
Roll-Forward 방식 (채택):Roll-Forward approach (adopted):
100(잔액) → 20(출금) → 80(잔액) → 실패 → [20(출금 취소 & 입금) 신규 이벤트 추가] → 100(잔액)
기존 원장을 절대 변경하지 않고, 신규 보상 이벤트를 추가하여 실패를 처리한다. 이를 통해 모든 거래 이력의 감사 추적성(Audit Trail)을 완벽하게 보존한다.The existing ledger is never modified. Failures are handled by appending compensating events, perfectly preserving the Audit Trail of all transaction history.
| 유형Type | 처리 방식Handling |
|---|---|
| 일시적 실패Transient failure | Exponential Backoff 재시도 (최대 N회)Exponential Backoff retry (up to N times) |
| 영구적 실패Permanent failure | 최대 N회 초과 시 → 거래 중지 → 개발팀 알림 전송 & 수기 대응Exceeds max N retries → halt trading → alert dev team & manual intervention |
Cancelled (주문 취소)Cancelled (Order Cancellation)
미체결 또는 부분 체결 주문에 대해 오더북 제거 → Fund Lock 해제(pending → available) → Outbox를 통해 취소 이벤트 발행의 순서로 처리한다.For unfilled or partially filled orders: remove from orderbook → release Fund Lock (pending → available) → publish cancel event via Outbox.
3-3. 동시성 제어 설계3-3. Concurrency Control Design
금융 서비스에서 동시성 문제는 자산 이중 차감, 중복 체결 등 치명적인 장애로 직결된다. SQS FIFO와 MongoDB를 활용하여 User-Level과 Market-Level 양쪽에서 동시성을 제어했다.In financial services, concurrency issues directly lead to critical failures such as double-deduction of assets and duplicate fills. Concurrency is controlled at both User-Level and Market-Level using SQS FIFO and MongoDB.
User-Level 동시성 제어User-Level Concurrency Control
| 기법Technique | 구현Implementation | 목적Purpose |
|---|---|---|
| 멱등성 검증Idempotency | MongoDB Unique Index (idempotency_key) |
동일 요청의 중복 실행 방지 (네트워크 재시도 등)Prevent duplicate execution of identical requests (e.g. network retries) |
| Distributed Lock | MongoDB Unique Index (lock:<USER_ID>) + TTL |
동일 사용자의 동시 주문 요청 직렬화Serialize concurrent order requests from the same user |
-
멱등성 검증: 클라이언트가 전달한
idempotency_key를 MongoDB Unique Index로 관리. 동일 키로 재요청 시 Insert 실패로 중복 실행을 원천 차단하고, 기존 처리 결과를 반환Idempotency: Client-providedidempotency_keymanaged via MongoDB Unique Index. Duplicate requests with the same key fail on insert, returning the existing result - Distributed Lock: 사용자별 Lock Document를 MongoDB에 Insert하여 동시 주문 직렬화. TTL Index를 활용해 비정상 종료 시에도 Lock이 자동 해제되도록 설계Distributed Lock: Lock Document per user inserted into MongoDB for order serialization. TTL Index ensures automatic lock release on abnormal termination
Market-Level 동시성 제어Market-Level Concurrency Control
하나의 마켓에 동시에 들어오는 다수의 주문이 매칭 순서를 엄격하게 보장해야 한다. 이를 위해 SQS FIFO Queue의 MessageGroupId를 활용했다.Multiple orders arriving simultaneously in a single market must strictly guarantee matching order. SQS FIFO Queue's MessageGroupId was leveraged for this.
-
동일 마켓의 주문은
MessageGroupId = market_id로 그룹핑하여 FIFO 순서 보장Orders in the same market are grouped byMessageGroupId = market_idfor FIFO ordering - 서로 다른 마켓의 주문은 병렬로 독립 처리 — 마켓 간 간섭 없음Orders in different markets are processed independently in parallel — no cross-market interference
-
SQS FIFO의
MessageDeduplicationId로 발행 시점 중복 제거 + Worker의processed_eventsUnique Index 멱등성 체크로 결과적 Exactly-Once 의미론 구현SQS FIFOMessageDeduplicationIdfor publish-time deduplication + Workerprocessed_eventsUnique Index idempotency check for effective Exactly-Once semantics
3-4. Transactional Outbox 패턴3-4. Transactional Outbox Pattern
도입 배경Background
분산 시스템에서 "DB에 저장 → 메시지 브로커에 발행"을 두 단계로 처리하면, 중간에 장애가 발생할 경우 DB는 커밋되었으나 메시지는 유실되는 불일치가 생긴다.
또한 이러한 2-Phase Commit은 동기 순차 실행으로 성능 저하가 크고 브로커가 지원하지 않는 경우도 많다.
Transactional Outbox 패턴을 도입하여, DB 쓰기와 이벤트 발행의 원자성을 보장했다.In distributed systems, handling "save to DB → publish to broker" in two steps can cause inconsistency where DB is committed but the message is lost if a failure occurs in between. 2PC (2-Phase Commit) has significant performance overhead and is often unsupported by brokers. The Transactional Outbox pattern was introduced to guarantee atomicity between DB writes and event publishing.
각 사이드별 역할Role of Each Side
Market Queue Worker Side
매칭 엔진이 체결 결과를 in-memory에 보관한 채, Outbox Event만 먼저 DB에 저장한다. 온체인 정산 결과가 확인된 후에 비로소 비즈니스 데이터를 DB에 커밋한다. 브로커를 직접 호출하지 않기 때문에 브로커 장애에 영향을 받지 않는다.The matching engine holds matched results in memory, saving only the Outbox Event to DB first. Business data is committed to DB only after on-chain settlement is confirmed. Since the broker is never called directly, broker failures have no impact.
# Pseudocode — Market Queue Worker
async def process_matched_order(matched_result):
# 1. 체결 결과를 in-memory에 보관
commit_data = matched_result.prepare_commit()
# 2. Outbox Event만 먼저 DB에 저장
outbox_event = OutboxEvent(
aggregate_id=matched_result.order_id,
event_type="ORDER_MATCHED",
payload=matched_result.to_settlement_payload(),
idempotency_key=matched_result.idempotency_key,
published_at=None, # 미발행 상태
)
await outbox_col.insert_one(outbox_event)
# 3. 온체인 Task 수행 동안, DB 커밋에 필요한 데이터를 미리 정리
commit_data.prepare_ledger_entries()
commit_data.prepare_balance_updates()
# 4. Relay가 온체인 정산 발행 → 온체인 결과 폴링 (최대 30초)
on_chain_result = await poll_on_chain_result(
outbox_event.id, timeout=30
)
# 5. 온체인 성공 확인 후 비즈니스 데이터 커밋
if on_chain_result.success:
async with db.transaction() as session:
await orders_col.update_one(commit_data, session=session)
await ledger_col.insert_one(commit_data.ledger, session=session)
else:
# 폴링 실패 → 매칭 취소 처리
raise SettlementTimeoutError()
Relay Side (OutboxRelay)
별도 프로세스로 동작하며, published_at이 None인 미발행 이벤트를 주기적으로 폴링하여 SQS FIFO에 Publish한 뒤 발행 완료를 마킹한다.Runs as a separate process, periodically polling unpublished events (published_at == None), publishing them to SQS FIFO, and marking them as published.
# Pseudocode — Relay Side
async def relay_loop():
while True:
events = await outbox_col.find(
{"published_at": None},
sort=[("created_at", 1)],
limit=BATCH_SIZE,
)
for event in events:
await sqs.send_message(
queue_url=FIFO_QUEUE_URL,
message_body=event.payload,
message_group_id=event.aggregate_id,
message_deduplication_id=str(event.id),
)
await outbox_col.update_one(
{"_id": event.id},
{"$set": {"published_at": utcnow()}},
)
await asyncio.sleep(POLLING_INTERVAL)
Worker Side (Consumer)
SQS FIFO에서 메시지를 수신하여 후속 처리를 실행한다. Relay가 미발행 이벤트(published_at: null)를 주기적으로 재폴링하여 at-least-once 전달을 구현하므로, 중복 메시지 수신 가능성에 대비하여 processed_events Collection의 Unique Index로 멱등성 체크를 수행한다.Receives messages from SQS FIFO for downstream processing. Since Relay implements at-least-once delivery by periodically re-polling unpublished events (published_at: null), idempotency checks are performed via processed_events Collection Unique Index to handle potential duplicates.
# Pseudocode — Worker Side
async def process_message(message):
event = parse(message.body)
# 1. 멱등성 체크
try:
await processed_col.insert_one(
{"event_id": event.id, "processed_at": utcnow()}
) # Unique Index on event_id
except DuplicateKeyError:
return # 이미 처리된 이벤트 → Skip
# 2. 후속 처리 (Settlement, Notification 등)
match event.event_type:
case "ORDER_MATCHED":
await settlement_service.execute(event)
case "ORDER_CANCELLED":
await notification_service.notify(event)
case "SETTLEMENT_COMPLETED":
await balance_service.confirm(event)
3-5. Event Sourcing + CQRS3-5. Event Sourcing + CQRS
Event Store + View ProjectionEvent Store + View Projection
모든 주문 / 매칭 / 정산 이벤트를 Append-Only Event Store에 기록하고, 조회 전용 데이터는 별도의 View Store로 Projection하는 CQRS 패턴을 적용했다.All order / matching / settlement events are recorded in an Append-Only Event Store, and read-only data is projected to a separate View Store using the CQRS pattern.
Event Store:
- 모든 상태 변경을 이벤트로 기록 (Append-Only, 삭제 / 수정 없음)All state changes recorded as events (Append-Only, no deletion / modification)
- 주문 생성, 매칭, 정산, 취소, 실패 복구 등 전체 거래 이력의 단일 진실 소스(Single Source of Truth)Order creation, matching, settlement, cancellation, failure recovery — Single Source of Truth for all trade history
- 감사 추적(Audit Trail) 및 장애 시 상태 재구축(Replay) 가능Enables Audit Trail and state reconstruction (Replay) on failure
View Store:
- Event Store에서 조회에 필요한 데이터만 Projection하여 저장Projects and stores only the data needed for queries from the Event Store
- 사용자 잔액, 오더북 현황, 거래 내역 등 읽기 전용 최적화 데이터User balances, orderbook status, trade history — read-optimized data
- Command 부하와 Query 부하를 분리하여 각각 독립적으로 스케일링 가능Separates Command and Query loads for independent scaling
적용 예시:Example:
- Event Store: 온체인에서 발생한 로우(raw) 이벤트를
BlockEventsCollection에 원본 그대로 Append-Only로 수집Event Store: Raw on-chain events collected as-is intoBlockEventsCollection in Append-Only fashion - View Store: 서비스에서 제공해야 하는 데이터만 Projection하여
TradeHistory,UserLeaderboard등 별도 Collection에 저장View Store: Only service-required data projected into separate Collections such asTradeHistory,UserLeaderboard
4. 성과 요약4. Results Summary
| 영역Area | 성과Achievement |
|---|---|
| 매칭 속도Matching Speed | Full On-Chain 대비 평균 체결 시간 10~15초 → 3~5초로 단축 (약 3배 개선)Average matching time reduced from 10–15s → 3–5s compared to full on-chain (approx. 3× improvement) |
| 가스비 절감Gas Cost Reduction | 주문 등록·매칭·취소의 온체인 처리를 제거하고 최종 정산만 온체인 기록 → 트랜잭션당 가스비 약 1/3 수준으로 절감Eliminated on-chain processing for order placement, matching, and cancellation — only final settlement recorded on-chain → gas cost reduced to approx. 1/3 per transaction |
| OrderBook Engine | Off-Chain 매칭 + On-Chain 정산 Hybrid 구조로, 매칭 속도와 정산 신뢰성 동시 확보Hybrid Off-Chain matching + On-Chain settlement — achieving both matching speed and settlement reliability |
| 이벤트 신뢰성Event Reliability | Transactional Outbox 패턴으로 DB 쓰기와 이벤트 발행의 원자성 보장, 메시지 유실 원천 차단Transactional Outbox pattern guarantees atomicity of DB writes and event publishing, eliminating message loss |
| 동시성 제어Concurrency | SQS FIFO 마켓별 순서 보장 + MongoDB Unique Index 기반 멱등성 / Distributed LockSQS FIFO per-market ordering + MongoDB Unique Index-based idempotency / Distributed Lock |
| 장애 복구Failure Recovery | Append-Only 원장 + Roll-Forward 전략으로 데이터 무결성 보존Append-Only ledger + Roll-Forward strategy preserving data integrity |
| 정산 안전성Settlement Safety | BSC 온체인 컨펌 30초 타임아웃, 실패 시 DB 커밋 없이 매칭 취소로 자산 안전 보장BSC on-chain confirm 30-second timeout; on failure, match cancelled without DB commit ensuring asset safety |
| 논스 복구Nonce Recovery | 제로 서명(빈 서명) 메커니즘으로 펜딩 논스 강제 소비, 오퍼레이터 큐 정상화Zero signature (empty signature) mechanism for force-consuming pending nonces, normalizing operator queues |
| 아키텍처Architecture | DDD + Hexagonal Architecture로 도메인 순수성 확보, 인프라 변경에 대한 유연성DDD + Hexagonal Architecture for domain purity and infrastructure flexibility |
| 데이터 설계Data Design | Event Sourcing + CQRS로 완전한 감사 추적성 및 Command / Query 독립 스케일링Event Sourcing + CQRS for complete audit trail and independent Command / Query scaling |