피드로 돌아가기
Scaling a Self-Hosted Billing Monitor from 1 to 100 Tenants
Dev.toDev.to
Backend

BillingWatch가 row-level isolation 패턴으로 100개 테넌트 환경의 멀티테넌시 아키텍처를 구현한 과정과 핵심 구현 기법을 소개합니다

Scaling a Self-Hosted Billing Monitor from 1 to 100 Tenants

Ray2026년 3월 30일4intermediate

Context

BillingWatch는 단일 Stripe 계정 전용으로 설계되었다. 사용자가 증가하면서 100개 테넌트规模的 확장이 필요해졌다. 각 테넌트가 독립된 Stripe 웹훅을 보유하고 중복 처리를 방지해야 하는 요구사항이 있었다.

Technical Solution

  • 테이블 구조 → tenant_id 컬럼을 모든 테이블에 추가하여 행 수준 테넌트 격리 적용
  • FastAPI → x-tenant-id 헤더 기반 쿼리 스코프 방식으로 요청별 테넌트 식별
  • 웹훅 라우팅 → /webhook/{tenant_token} 경로로 각 테넌트별 고유 엔드포인트 할당
  • 멱등성 보장 → ProcessedEvent 테이블에 (event_id, tenant_id) 복합 인덱스 구성
  • SQLite 확장 → WAL 모드와 synchronous=NORMAL 프라그마 활성화로 동시성 향상
  • Rate Limiting → tenant_id별 in-memory 카운터로 60초 윈도우당 100회 제한

Impact

SQLite + WAL 모드로 100개 테넌트의 중등도 웹훅 볼륨 처리 가능. 복합 인덱스 추가로 수백만 건 레코드에서도 빠른 조회 성능 유지.

Key Takeaway

테넌트 격리는 처음부터 row-level 방식으로 구현해야 한다. 나중에 리팩토링하면 비용이 크다.


멀티테넌트 SaaS 환경에서 Stripe 웹훅 처리 시 고유 tenant_token 기반 엔드포인트 분리 + ProcessedEvent 테이블 멱등성 처리 + tenant별 rate limiting 조합으로 확장 가능한 아키텍처 구현 가능

원문 읽기