--- id: wiki-2026-0508-saas title: SaaS (Software as a Service) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Software as a Service, Cloud Software, Multi-tenant SaaS] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [saas, multi-tenancy, subscription, ai-native, vertical-saas] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Next.js / Stripe / Postgres RLS --- # SaaS (Software as a Service) ## 매 한 줄 > **"매 multi-tenant, subscription-based, browser-delivered software — 매 install 의 X, 매 always-latest"**. 매 1999 Salesforce ("End of Software") 로 출발 → 매 2010s SaaS 1.0 (horizontal CRM/HR) → 매 2020s vertical SaaS (Toast, Procore, Veeva) → 매 2026 AI-native SaaS (Glean, Harvey, Cursor) 가 매 outcome-based pricing 으로 매 seat-based 모델 을 흔드는 시기. ## 매 핵심 ### 매 Pillars - **Multi-tenancy**: tenant-isolated data on shared infra (RLS, schema-per-tenant, DB-per-tenant). - **Subscription**: MRR/ARR, Stripe billing, dunning, proration. - **Self-serve onboarding**: PLG funnel, time-to-value 분 단위. - **Continuous delivery**: weekly/daily ship, no version skew. - **Observability**: per-tenant SLO, usage analytics, churn signals. ### 매 SaaS metrics - **ARR/MRR**, **NRR** (Net Revenue Retention) — best signal of product fit. - **CAC payback** — months to recoup acquisition. - **Magic Number** = (ΔARR × 4) / S&M spend. - **Gross margin** — typical SaaS 70-85%, AI-SaaS 50-70% (inference cost). - **LTV/CAC** ≥ 3, payback ≤ 12 months. ### 매 Pricing models - **Per-seat**: classic Salesforce/Slack — saturating in AI era. - **Usage-based**: Snowflake, Twilio, OpenAI — aligns to value. - **Outcome/agent-based**: 2026 AI-native — pay per resolved ticket, per qualified lead. - **Hybrid**: platform fee + usage overage. ### 매 응용 1. Horizontal SaaS (CRM, HRIS, ITSM, comms). 2. Vertical SaaS (legal, dental, construction, hospitality). 3. Developer SaaS (GitHub, Vercel, Sentry). 4. AI-native SaaS (Cursor, Glean, Harvey, Decagon). 5. Embedded SaaS (in-app commerce, fintech). ## 💻 패턴 ### Multi-tenant Postgres RLS ```sql ALTER TABLE documents ENABLE ROW LEVEL SECURITY; CREATE POLICY tenant_isolation ON documents USING (tenant_id = current_setting('app.tenant_id', true)::uuid); -- App connection middleware SET LOCAL app.tenant_id = '7f3a...'; ``` ### Stripe subscription with proration ```typescript import Stripe from 'stripe' const stripe = new Stripe(process.env.STRIPE_SECRET!) await stripe.subscriptions.update(subId, { items: [{ id: itemId, price: 'price_pro_monthly', quantity: 25 }], proration_behavior: 'create_prorations', billing_cycle_anchor: 'unchanged', }) ``` ### Usage-based metering (Stripe meters, 2026) ```typescript await stripe.billing.meterEvents.create({ event_name: 'api_calls', payload: { stripe_customer_id: customer.id, value: '1', }, }) // Subscribe customer to metered price; Stripe aggregates and bills monthly ``` ### Tenant context middleware (Next.js) ```typescript // app/middleware.ts import { NextResponse } from 'next/server' export async function middleware(req: Request) { const session = await getSession(req) const tenantId = session?.tenantId if (!tenantId) return NextResponse.redirect('/login') const res = NextResponse.next() res.headers.set('x-tenant-id', tenantId) return res } ``` ### Per-tenant rate limit (Upstash Redis) ```typescript import { Ratelimit } from '@upstash/ratelimit' import { Redis } from '@upstash/redis' const limiters = new Map() function tenantLimiter(plan: 'free' | 'pro' | 'enterprise') { const limits = { free: 100, pro: 1000, enterprise: 10000 } return new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(limits[plan], '1 m'), }) } ``` ### PLG signup with magic-link (no password) ```typescript // Send magic link, no password friction const token = jwt.sign({ email, tenantId: nanoid() }, SECRET, { expiresIn: '15m' }) await sendEmail(email, `https://app.example.com/auth?t=${token}`) // On click: provision trial tenant, redirect to onboarding wizard ``` ### AI-native SaaS — usage-aware inference cost ```typescript async function chat(tenantId: string, msgs: Message[]) { const tier = await getTier(tenantId) const model = tier === 'enterprise' ? 'claude-opus-4-7' : 'claude-haiku-4-5' const resp = await anthropic.messages.create({ model, max_tokens: 1024, messages: msgs, metadata: { user_id: tenantId }, }) await meterUsage(tenantId, { input_tokens: resp.usage.input_tokens, output_tokens: resp.usage.output_tokens, model, }) return resp } ``` ### Outcome pricing instrumentation ```typescript // Charge only when AI agent successfully resolved async function recordResolution(tenantId: string, ticketId: string, resolved: boolean) { if (resolved) { await stripe.billing.meterEvents.create({ event_name: 'resolved_ticket', payload: { stripe_customer_id: tenantId, value: '1' }, }) } } ``` ### Tenant-isolated S3 (per-prefix IAM) ```python # Generate scoped STS token per tenant request sts = boto3.client("sts") policy = {"Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"], "Resource": [f"arn:aws:s3:::tenants-bucket/{tenant_id}/*"], }]} creds = sts.assume_role( RoleArn=ROLE, RoleSessionName=f"tenant-{tenant_id}", Policy=json.dumps(policy), DurationSeconds=900, ) ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Early-stage horizontal | Shared schema + RLS, Stripe per-seat | | Vertical w/ compliance | Schema-per-tenant or DB-per-tenant | | AI-native, variable cost | Usage-based + cap to protect margin | | Enterprise w/ SOC2/HIPAA | Single-tenant deploy option, BYOC | | PLG self-serve | Magic-link + provisioned trial in <60s | **기본값**: shared-DB RLS + hybrid pricing (platform fee + usage) + Stripe meters + PLG onboarding. ## 🔗 Graph ## 🤖 LLM 활용 **언제**: in-product copilot, customer support deflection, churn prediction from usage signals, content/email generation, dynamic onboarding. **언제 X**: pricing/billing computation — must be deterministic for audit and revenue recognition. ## ❌ 안티패턴 - **No tenant isolation**: WHERE tenant_id checked only in app layer → IDOR breach. - **Per-seat pricing for AI**: high-usage user breaks margin; need usage cap or tier. - **Free tier without limits**: abuse → infra cost spirals. - **Single-region SaaS for global**: latency + data residency violations (GDPR). - **No self-serve cancel**: regulatory risk (FTC click-to-cancel 2024) + churn spikes. - **Version skew**: different customers on different versions → support combinatorics explode. ## 🧪 검증 / 중복 - Verified (a16z SaaS metrics, OpenView PLG benchmarks, Stripe Billing docs, AWS SaaS Lens). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — multi-tenancy, pricing models, AI-native SaaS 2026 |