--- title: Multi-tenancy Isolation 패턴 (Pool vs Silo vs Bridge) source_type: llm-generated status: draft confidence: medium tags: [multi-tenancy, saas, isolation] related_projects: [ca-skeleton] last_reviewed: 2026-05-22 --- # Multi-tenancy Isolation 패턴 (Pool vs Silo vs Bridge) > Layer: `wiki/concepts/` — 일반 개념. 실제 적용은 `wiki/projects/` 또는 raw 브랜치 노트 참조. ## Summary Multi-tenancy isolation은 "여러 tenant가 같은 소프트웨어 인스턴스를 어느 수준까지 공유하는가"의 스펙트럼이다. AWS SaaS Lens는 이를 **Silo / Pool / Bridge** 3분류로 정리하고, Hibernate는 ORM 레벨에서 **DATABASE / SCHEMA / DISCRIMINATOR** 3 strategy로 공식 지원하며, Azure는 **Deployment Stamps** 패턴으로 hybrid를 다룬다. ca-tmpl은 **opt-in(`APP_TENANT_ENABLED=true` 시만 활성) + shared DB + `tenant_id` column(ULID) + JWT claim 우선 resolution** 조합을 baseline으로 채택한다. 이는 AWS Pool 모델 + Hibernate DISCRIMINATOR 전략에 해당하며, B2B 초기 단계(tenant 수 수십~수백 단위)에 isolation 비용 대비 운영 단순성을 우선한 의도적 선택이다. opt-in 설계의 의의는 single-tenant deployment에서는 tenant 로직 자체를 비활성화하여 skeleton의 적용 범위를 넓힌 점에 있다. **Migration trigger 3가지**는 (a) 규제(금융·의료) isolation 강제, (b) tenant 수 수백~수천 + 단일 row 수 수억 도달, (c) enterprise tier 등장으로 isolation을 가격에 반영해야 할 때다. ## Standard (공식 정의) ### AWS SaaS Tenant Isolation Strategies (Whitepaper) — Silo / Pool / Bridge - **Silo**: tenant마다 별도 stack(compute/DB/network까지 분리). isolation 최강, 비용 최대. - **Pool**: 모든 tenant가 동일 infra와 schema를 공유, `tenant_id` 컬럼으로 row-level 구분. - **Bridge**: 일부 리소스는 silo, 일부는 pool. 예) DB는 silo, app server는 pool. - AWS는 "Authentication is not isolation. You must enforce isolation at the resource layer"라고 명시한다. ### Hibernate ORM Multi-tenancy — DATABASE / SCHEMA / DISCRIMINATOR - **DATABASE**: tenant별 별도 데이터베이스. - **SCHEMA**: 동일 DB, tenant별 별도 schema. - **DISCRIMINATOR**: 동일 schema, `tenant_id` 컬럼. Hibernate 6부터 native 지원(이전엔 Filter로 우회). - 활성화는 `hibernate.tenant_identifier_resolver` + `hibernate.multi_tenant_connection_provider` 설정으로 수행. `CurrentTenantIdentifierResolver`가 ThreadLocal/SecurityContext에서 tenant를 결정. ### Azure Architecture Center — Deployment Stamps (Hybrid) - Tenancy를 "fully shared → shared compute, isolated DB → isolated stamp → isolated subscription" **스펙트럼**으로 정의. - **Deployment Stamps**: 동일한 스택을 단위(stamp)로 복제하고, stamp 안에 N개 tenant를 pool. tier별로 stamp 크기와 isolation 수준을 다르게 둘 수 있음. - Microsoft는 "There's no single right approach to multitenancy"라고 명시 — 비즈니스 모델·규제·확장성·비용에 따라 모델이 달라진다. ### Tenant Resolution 방식 (isolation과 직교) - **JWT claim**: token 서명 검증으로 위변조 방지. 가장 안전. - **Subdomain (`{tenant}.app.com`)**: UX 친화적, 단 wildcard DNS/TLS 필요. - **Custom header (`X-Tenant-Id`)**: 단순하나 외부 trust boundary에서 단독 신뢰 금지. - **Path (`/t/{tenant}/...`)**: routing 자연스럽지만 모든 client URL 변경. ## 한계 / 주의점 각 대안의 한계는 다음과 같다. ### shared DB + tenant_id (Pool / Hibernate DISCRIMINATOR) - **Noisy neighbor**: hot tenant가 같은 인스턴스 전체에 영향. - **규제 isolation 불가**: application bug 한 줄로 cross-tenant leak 가능. HIPAA·FedRAMP·금융권은 storage 레벨 분리를 요구하는 경우가 있어 Pool로 충족 어려움. - **Index 비용**: tenant로 filter하는 모든 index에 `tenant_id`를 leading column으로 포함해야 plan이 효율적. - **Native query/JDBC bypass 위험**: JPQL 경로 외에서 tenant filter 누락 시 leak. ### Subdomain-based resolution - **Wildcard DNS와 wildcard TLS 인증서** 필요. custom domain 지원 시 per-domain 인증서 자동화 추가. - Let's Encrypt rate limit은 "registered domain당 주 50개 인증서"로 보고되나 — 정확 수치와 적용 범위는 `needs-confirmation` (raw 발췌 기준). - **DNS propagation 지연**, **subdomain takeover 위험**(tenant 삭제 후 DNS record 미정리), **CORS/cookie domain 설정 복잡성**. - Local dev는 `lvh.me`/`nip.io`/hosts 수정 필요. ### JWT claim only - claim 검증을 한 곳이라도 빠뜨리면 cross-tenant 위험. - token 재발급 없이 tenant 전환 불가 → admin/support 운영 동선 제약. - IdP와 강결합 → tenant 정보 변경 시 token rotation 정책 필요. ### Schema-per-tenant (Hibernate SCHEMA) - Postgres metadata(`pg_class`, `pg_attribute`) overhead가 tenant 수 증가에 따라 누적. - Stripe/Citus 자료에 따르면 "수백~수천 tenant"에서 catalog bloat·autovacuum·plan cache miss가 문제로 보고됨 — 다만 정확한 임계 수치 인용은 `needs-confirmation`. - **Connection pooling 난이도**: `search_path` 전환이 plan cache를 무효화. HikariCP per tenant vs single pool 설계 선택 필요. - 마이그레이션이 tenant 수만큼 반복(Flyway `schemas` 옵션으로 일괄 처리 가능하나 추가/삭제 자동화 필요). ### Database-per-tenant (Silo) - Isolation 가장 강함, **운영 비용 폭증**: 마이그레이션·백업·모니터링이 모두 tenant 수에 비례. - Connection pool이 (tenant 수 × pool size)로 폭발 → connection multiplexing(예: PgBouncer) 필수. - AWS 계정·서비스 limit에 부딪힐 수 있음. - 비용은 silo > bridge > pool 순. ### Hybrid (Azure Deployment Stamps / AWS Bridge) - 두 가지 이상 모델을 동시 운영 → **운영 복잡도 최고**. - Tier 승급(pool → silo) 시 **데이터 이동 절차** 필요. - Routing layer + tenant catalog가 사실상 control plane이 되어, 가용성 single point가 되지 않도록 분산 필요. - 작은 팀에서 도입하면 ROI 부정. 일반적으로 product-market fit 이후 단계에서 검토. ### 공통 오해 - "Pool이면 무조건 싸다"는 거짓 — 노이즈/검증 비용이 일정 규모 이상에선 silo와 역전될 수 있음. - "Subdomain이면 자동 isolation" 거짓 — resolution과 isolation은 직교. subdomain은 routing일 뿐 storage 분리를 보장하지 않음. - "JWT claim만 있으면 안전" 거짓 — repository·query 레이어에서 tenant filter를 강제하지 않으면 claim의 의미가 없음. ## Project Application - [[wiki/projects/ca-tmpl/multi-tenancy-isolation-patterns]] — ca-tmpl 의사결정 기록 (현재 `documented-only`, Phase C2 미진입). 실제 구현 여부는 project 문서 참조. ca-tmpl은 본 개념을 다음 위치에서 적용·문서화한다. concept 문서는 등급을 매기지 않으며, 검증 수준은 각 프로젝트/브랜치 노트에서 판정한다. - [[raw/branch-notes/feature-tenant-context-policy]] — tenant resolution(JWT > header admin only > subdomain fallback) + isolation SSOT - [[raw/branch-notes/feature-repository-access-permission-contract]] — `CROSS_TENANT_ADMIN` capability, repository 레벨 tenant filter 강제 contract - [[raw/project-notes/ca-skeleton-operational-contract]] — §10 Repository Access Permission Contract, §29 Topic 6 Multi-tenancy Isolation ## Interview Questions - AWS SaaS Lens의 Pool/Silo/Bridge는 무엇이 다르고, 어떤 상황에서 어떤 모델을 선택하나? - Tenant ID를 JWT claim과 HTTP header 중 어디서 읽어야 하며, 둘을 동시에 허용한다면 어떤 trust 기준을 두는가? - shared DB + tenant_id에서 schema-per-tenant 또는 db-per-tenant로 마이그레이션을 트리거하는 조건은 무엇인가? - Cross-tenant 침해를 막기 위해 어느 레이어(JWT 검증 / SecurityContext / repository / DB)에 어떤 방어가 필요한가? - Tenant 식별자에 ULID와 UUID 중 어느 쪽을 쓰는 게 적합하며, 각 선택의 trade-off는 무엇인가? ## Do Not Overclaim - "shared DB + tenant_id가 항상 우월하다"고 말하지 말 것 — 규제 산업·data residency 요구가 있는 도메인에서는 Silo가 필수 또는 사실상 강제다. - Stripe/Citus의 schema-per-tenant 한계치(예: "정확히 N tenant에서 한계")는 **정확 인용 wording이 미완**이며 raw 자료는 `needs-confirmation` 상태다. 면접/이력서에서는 "수백~수천 단위에서 catalog overhead가 보고된다" 정도로 출처(Citus blog)와 함께만 언급할 것. - "Atlassian이 그렇게 하니까 best practice"라고 말하지 말 것 — company-tech-blog 사례는 관점·증거이지 공식 기준이 아니다. - "JWT claim만 검증하면 multi-tenant가 안전하다"는 단정 금지 — claim은 입구일 뿐 storage layer 강제가 별도로 필요하다. - ca-tmpl 적용 사실(예: ULID 채택 이유, capability 설계)은 본 concept 문서가 아니라 `wiki/projects/` 또는 branch-notes에서 검증 등급과 함께 진술할 것. "내가 했다"는 표현은 concept 레이어에 두지 않는다. ## Sources - [AWS Whitepaper — SaaS Tenant Isolation Strategies](https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies/saas-tenant-isolation-strategies.html) — Silo/Pool/Bridge 분류 baseline - [Hibernate ORM User Guide — Multi-tenancy](https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#multitenacy) — DATABASE/SCHEMA/DISCRIMINATOR 공식 strategy - [Azure Architecture Center — Multitenant SaaS](https://learn.microsoft.com/en-us/azure/architecture/guide/multitenant/overview) — Deployment Stamps / hybrid spectrum - [Citus — Designing your SaaS DB for High Scalability](https://www.citusdata.com/blog/2016/10/03/designing-your-saas-database-for-high-scalability/) — schema vs shared schema 한계치 (company-tech-blog, needs-confirmation) - [Auth0 — Multi-tenant applications](https://auth0.com/docs/get-started/auth0-overview/create-tenants/multiple-tenants) — tenant resolution(subdomain/JWT/header) 비교 - [Vercel — Multi-tenant Next.js Guide](https://vercel.com/guides/nextjs-multi-tenant-application) — subdomain routing 실무 - [AWS APN Blog — Hybrid Tenant Isolation](https://aws.amazon.com/blogs/apn/) — tier-based hybrid 사례 - [Atlassian Engineering — Cloud Architecture Guidelines](https://www.atlassian.com/engineering/cloud-architecture-and-guidelines) — shard 단위 isolation + tenant context propagation 사례 - [[raw/official-docs/multitenancy-aws-saas-tenant-isolation-whitepaper]] - [[raw/official-docs/multitenancy-hibernate-user-guide]] - [[raw/official-docs/multitenancy-azure-architecture-patterns]] - [[raw/company-tech-blogs/multitenancy-stripe-citus-schema-per-tenant]] - [[raw/company-tech-blogs/multitenancy-auth0-tenant-resolution]] - [[raw/company-tech-blogs/multitenancy-subdomain-resolution-patterns]] - [[raw/company-tech-blogs/multitenancy-hybrid-pooled-siloed-mix]] - [[raw/company-tech-blogs/multitenancy-atlassian-tenant-context]] - [[raw/project-notes/ca-skeleton-operational-contract]] — §10, §29 Topic 6