124 lines
11 KiB
Markdown
124 lines
11 KiB
Markdown
---
|
|
title: Idempotency 저장소 — Redis 기반 vs DB 기반 trade-off
|
|
source_type: company-tech-blog
|
|
url: https://docs.aws.amazon.com/powertools/python/latest/utilities/idempotency/
|
|
archive_url:
|
|
status: raw
|
|
confidence: medium
|
|
tags: [ca-idempotency, storage-tradeoff, redis-vs-db, durability, dynamodb]
|
|
related_projects: [ca-skeleton-operational-contract]
|
|
related_branches: [feature-rate-limit-idempotency-contract, feature-api-contract-baseline]
|
|
created: 2026-05-22
|
|
last_reviewed: 2026-05-27
|
|
---
|
|
|
|
# Idempotency 저장소 — Redis 기반 vs DB 기반
|
|
|
|
> Layer: `raw/company-tech-blogs/` — **종합 비교 노트**. 단일 출처가 아닌 4개 1차 출처(Brandur / AWS Powertools / Toss / Stripe) 의 cross-reference. 본 자료 자체는 합성 — Strength 는 cited primary source 의 등급을 따른다.
|
|
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성.
|
|
|
|
## Parent / 활용 branch (필수)
|
|
|
|
| Branch | 이 자료가 정당화하는 결정 |
|
|
|---|---|
|
|
| [[raw/branch-notes/feature-rate-limit-idempotency-contract]] | ca-tmpl 의 DB table 기반 저장 선택의 trade-off 비교 base. Redis 대안을 명시적으로 검토했다는 evidence |
|
|
| [[raw/branch-notes/feature-api-contract-baseline]] | API contract 의 idempotency 동작 (TTL, in-flight handling) 의 저장소별 차이 |
|
|
| [[raw/project-notes/ca-skeleton-operational-contract]] | §13. API Contract Surface + §18. Control Plane Contract 의 저장소 선택 합리화 |
|
|
|
|
## 컨텍스트
|
|
|
|
ca-tmpl 의 **"DB table 기반 저장"** 선택을 Redis 대안과 명시적으로 비교. 보조 대안 6. 본 노트는 종합 비교이므로 1차 출처의 직접 인용을 별도 raw 자료(`idempotency-brandur-stripe-postgres.md`, `idempotency-toss-payments-techblog.md`) 에서 참조.
|
|
|
|
## 출처 / Source
|
|
|
|
본 자료는 종합 비교 노트. 1차 출처는 별도 raw 자료로 보관:
|
|
|
|
- **AWS Lambda Powertools (Python) — Idempotency utility** (`official-vendor-doc` 등급): https://docs.aws.amazon.com/powertools/python/latest/utilities/idempotency/
|
|
- **Brandur — Implementing Stripe-like Idempotency Keys in Postgres** (`engineering-blog` 등급): https://brandur.org/idempotency-keys → [[raw/company-tech-blogs/idempotency-brandur-stripe-postgres]]
|
|
- **토스페이먼츠 멱등키 가이드** (`official-vendor-doc` 등급): https://docs.tosspayments.com/guides/using-api/idempotency-key → [[raw/company-tech-blogs/idempotency-toss-payments-techblog]]
|
|
- **Stripe API Reference — Idempotent Requests** (`official-vendor-doc` 등급): https://stripe.com/docs/api/idempotent_requests
|
|
- 아카이브 URL: (미수집)
|
|
- 마지막 확인일: 2026-05-27
|
|
|
|
## 핵심 인용 / Key quotes (verbatim)
|
|
|
|
> [§Brandur — Reaper] "I'd suggest a threshold of about 72 hours so that even if a bug is deployed on Friday that errors a large number of valid requests, an app could still keep a record."
|
|
|
|
> [§AWS Powertools — Default persistence] "We use Amazon DynamoDB as the default persistence layer in the documentation."
|
|
|
|
> [§AWS Powertools — Cache alternative] "The `CachePersistenceLayer` enables you to use Valkey, Redis OSS, or any Redis-compatible cache as the persistence layer for idempotency state."
|
|
|
|
> [§AWS Powertools — Multi-backend support] "Support for Amazon DynamoDB, Valkey, Redis OSS, or any Redis-compatible cache as the persistence layer"
|
|
|
|
> [§AWS Powertools — TTL semantics] "We don't rely on DynamoDB or any persistence storage layer to determine whether a record is expired to avoid eventual inconsistency states. Instead, Idempotency records saved in the storage layer contain timestamps that can be verified upon retrieval and double checked within Idempotency feature."
|
|
|
|
> [§AWS Powertools — expiry_attr] "expiry_attr | `expiration` | Unix timestamp of when record expires"
|
|
|
|
## Claims Extracted / 추출된 주장
|
|
|
|
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
|
|---|---|---|---|---|---|
|
|
| REDIS-VS-DB-C1 | AWS Lambda Powertools 는 DynamoDB 를 **default persistence layer** 로 사용 | [§AWS Powertools — Default persistence] "We use Amazon DynamoDB as the default persistence layer in the documentation." | `official-vendor-doc` | AWS Lambda Powertools (Python) | 모든 AWS Lambda 사용자가 DynamoDB 를 써야 한다는 뜻은 아님. 단지 문서의 default |
|
|
| REDIS-VS-DB-C2 | Lambda Powertools 는 `CachePersistenceLayer` 로 Valkey / Redis OSS / Redis-compatible cache 도 지원 (alternative) | [§AWS Powertools — Cache alternative] "The `CachePersistenceLayer` enables you to use Valkey, Redis OSS, or any Redis-compatible cache as the persistence layer for idempotency state." | `official-vendor-doc` | Lambda Powertools idempotency utility | Redis 가 DynamoDB 보다 우수/열등하다는 결론은 본 인용에 없음 — 둘 다 옵션 |
|
|
| REDIS-VS-DB-C3 | Powertools 는 storage layer 의 TTL 에 만료 판정을 위임하지 않고, 레코드 내부 timestamp 를 retrieval 시 검증 (eventual inconsistency 회피 목적) | [§AWS Powertools — TTL semantics] "We don't rely on DynamoDB or any persistence storage layer to determine whether a record is expired ... Idempotency records saved in the storage layer contain timestamps that can be verified upon retrieval and double checked within Idempotency feature." | `official-vendor-doc` | Powertools idempotency 정확성 모델 | DynamoDB TTL 자체가 부정확하다는 뜻은 아님. Powertools 가 추가 검증 계층을 두는 설계 결정 |
|
|
| REDIS-VS-DB-C4 | DynamoDB 구성 시 만료 attribute 명칭은 기본 `expiration` (Unix timestamp) | [§AWS Powertools — expiry_attr] "expiry_attr \| `expiration` \| Unix timestamp of when record expires" | `official-vendor-doc` | DynamoDB-backed persistence layer 설정 | Redis backend 의 TTL 설정 방식이 동일하다는 뜻은 아님 (Redis 는 `EXPIRE` / `SET ... EX` 사용) |
|
|
| REDIS-VS-DB-C5 | Brandur 는 reaper threshold 를 약 **72시간** 권장 (금요일 버그 배포 대비 정당화) | [§Brandur — Reaper] "I'd suggest a threshold of about 72 hours so that even if a bug is deployed on Friday that errors a large number of valid requests, an app could still keep a record." | `engineering-blog` | Postgres 기반 DB storage 의 reaper 정책 | 72시간이 모든 도메인 표준이라는 뜻 아님. Toss 15일, Stripe v2 30일 등 다양 |
|
|
| REDIS-VS-DB-C6 | 결제 도메인 vendor reference 구현 (Stripe, Brandur, Toss) 은 모두 **영속 저장 (Postgres / DynamoDB 또는 비공개 영속 layer)** 사용 — Redis-only 는 reference 에 없음 | (종합 관찰 — 각 1차 출처는 별도 raw) | `needs-confirmation` | 결제·상태변경 도메인의 저장소 선택 | Stripe / Toss 가 내부적으로 Redis 를 캐시 layer 로 쓰지 않는다는 뜻은 아님 (내부 구현 비공개). 다른 vendor (Square, Adyen 등) 의 정책은 별도 |
|
|
|
|
## Usage Boundaries / 적용 경계
|
|
|
|
- **이 자료가 직접 증명하는 것**:
|
|
- `REDIS-VS-DB-C1` ~ `C4`: AWS Powertools 의 다중 backend 지원 사실 + TTL 검증 모델
|
|
- `REDIS-VS-DB-C5`: Brandur 의 72시간 reaper 권장
|
|
- **이 자료가 증명하지 않는 것**:
|
|
- "DB 가 Redis 보다 결제 도메인에 적합하다" 는 일반 결론 — Stripe/Toss 의 내부 저장소는 공개 안 됨
|
|
- 모든 결제 vendor 가 영속 저장을 쓴다는 것 (`C6` 은 관찰 + 비공개 가능성 인정 → `needs-confirmation`)
|
|
- Redis 의 durability (RDB/AOF) 가 idempotency 에 충분하지 않다는 결론
|
|
- Redlock 의 안전성에 대한 결론 (Kleppmann 비판은 별도 자료)
|
|
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
|
|
- ca-tmpl 의 도메인 (결제 vs 일반 mutation) 별 durability 요구 수준
|
|
- 200ms wait + DB row lock 패턴이 throughput SLA 와 충돌하는지
|
|
- Redis 선택 시 RDB/AOF 설정 + 노드 장애 시 키 유실 시나리오 측정
|
|
|
|
## 메모 / Notes
|
|
|
|
> 검증되지 않은 내 해석은 여기에 두지 말 것 — wiki source-summary 단계에서.
|
|
|
|
- **key scope**: 무관 (저장소 선택과 별개).
|
|
- **TTL**:
|
|
- Redis: TTL 컬럼이 1급 시민. `EXPIRE` / `SET ... EX` 로 자동 만료. 운영비 거의 0.
|
|
- DB: 명시적 reaper / TTL 컬럼 + 배치 삭제 필요. DynamoDB 는 TTL attribute 로 자동 (단 `C3` 처럼 Powertools 는 추가 검증).
|
|
- **저장소 (DB/Redis/in-memory)**: 본 노트의 핵심.
|
|
- **Redis 장점**: 낮은 latency (<1ms), 높은 처리량, TTL 자동, lock primitive (`SETNX`, Redlock) 풍부.
|
|
- **Redis 단점**: 결제 트랜잭션과 다른 시스템 → 정합성 boundary 추가. RDB/AOF 의존 durability. 노드 장애 시 키 유실 가능 → 이중 결제 위험. lock primitive(Redlock) 자체도 논쟁(Kleppmann 비판).
|
|
- **DB 장점**: 결제 트랜잭션과 같은 트랜잭션 boundary. ACID. 운영 가시성(SQL). atomic phase 모델로 부분 복구 가능.
|
|
- **DB 단점**: latency 더 큼. 인덱스/Vacuum 운영. 테이블 비대화.
|
|
- **duplicate 처리**:
|
|
- Redis: 키 조회 1-RTT, response cache 는 별도 메커니즘(value 에 JSON 저장 등).
|
|
- DB: 단일 SELECT/INSERT 로 키+response_code+response_body 일관 저장.
|
|
- **fingerprint (same key, different body)**: 저장소와 무관. 단 DB 는 JSONB 비교가 native 하고 인덱싱 가능, Redis 는 value 안에 hash 를 별도 저장해 비교 필요.
|
|
- **장점 (DB 선택의 일반론 — 미검증 추론)**:
|
|
- 결제/상태변경 도메인에서 **durability ≫ throughput**.
|
|
- 외부 상태 mutation 의 atomic phase 추적 가능.
|
|
- 운영 사고 시 SQL 단일 도구로 추적·복구.
|
|
- **단점 (추론)**:
|
|
- latency·처리량은 Redis 대비 손해.
|
|
- reaper 배치 운영 부담.
|
|
- **ca-tmpl 과의 차이**:
|
|
- ca-tmpl 은 **DB table 기반** 선택 → Stripe/Brandur reference 와 같은 계열.
|
|
- 200ms in-flight wait 는 DB row lock + short timeout 패턴과 자연스럽게 결합 (Redis Redlock 보다 단순·안전 — 단 미검증 일반화).
|
|
- 24h TTL 은 Brandur 72h 보다 짧아 테이블 크기·인덱스 비용을 더 보수적으로 관리.
|
|
- **결론: ca-tmpl 의 DB 선택은 결제·상태변경 도메인 reference 와 정합적. Redis 선택은 throughput 이 critical 하고 일시적 dedup 만 필요한 도메인에 적합.**
|
|
|
|
## Related / 관련
|
|
|
|
- 같은 주제 다른 raw:
|
|
- [[raw/company-tech-blogs/idempotency-brandur-stripe-postgres]] — DB 기반 1차 출처
|
|
- [[raw/company-tech-blogs/idempotency-toss-payments-techblog]] — vendor official 비교
|
|
- 인용하는 branch:
|
|
- [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
|
- [[raw/branch-notes/feature-api-contract-baseline]]
|
|
- 인용하는 project:
|
|
- [[raw/project-notes/ca-skeleton-operational-contract]] (§13, §18)
|
|
- 인용한 wiki 요약: (미작성)
|