[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-en-\u002Fblog\u002Fsaas-architecture-patterns-\u002Fen\u002Fblog\u002Fsaas-architecture-patterns":3,"blog-post-surround-en-\u002Fblog\u002Fsaas-architecture-patterns-\u002Fen\u002Fblog\u002Fsaas-architecture-patterns":5070,"related-posts-en-\u002Fblog\u002Fsaas-architecture-patterns-\u002Fen\u002Fblog\u002Fsaas-architecture-patterns":5079},{"id":4,"title":5,"authors":6,"badge":13,"body":15,"categories":5026,"date":5028,"description":5029,"extension":5030,"image":5031,"meta":5033,"navigation":240,"path":5063,"readingTime":261,"seo":5064,"stem":5065,"tags":5066,"__hash__":5069},"posts_en\u002Fblog\u002F13.saas-architecture-patterns.md","SaaS Architecture Patterns: Building Scalable Applications",[7],{"name":8,"to":9,"avatar":10,"bio":12},"Marcel Posdijk","https:\u002F\u002Fx.com\u002Fmarcelposdijk",{"src":11},"\u002Fimages\u002Fteam\u002Fmarcel.jpg","Founder and lead developer at Ludulicious B.V. with over 25 years of experience in web development and software architecture.",{"label":14},"Architecture",{"type":16,"value":17,"toc":4996},"minimark",[18,23,27,33,67,72,104,115,119,124,127,132,164,168,172,175,357,362,386,392,396,399,1373,1377,1402,1407,1411,1415,1418,2453,2457,2482,2487,2491,2494,3160,3164,3189,3194,3198,3202,3205,3327,3338,3342,3345,4156,4166,4170,4174,4184,4189,4218,4223,4682,4686,4690,4709,4713,4735,4739,4757,4761,4784,4788,4791,4868,4872,4875,4911,4915,4918,4921,4924,4949,4954,4961,4983,4986,4992],[19,20,22],"h2",{"id":21},"the-problem-saas-applications-that-dont-scale","The Problem: SaaS Applications That Don't Scale",[24,25,26],"p",{},"In 2023, we were building SaaS applications that worked fine with 100 users but collapsed under 10,000 users. Clients were frustrated with performance issues, and we were constantly firefighting scalability problems.",[24,28,29],{},[30,31,32],"strong",{},"The Challenge:",[34,35,36,43,49,55,61],"ul",{},[37,38,39,42],"li",{},[30,40,41],{},"Multi-tenancy",": Data isolation between customers",[37,44,45,48],{},[30,46,47],{},"Performance",": Slow queries as data grew",[37,50,51,54],{},[30,52,53],{},"Scalability",": Applications couldn't handle user growth",[37,56,57,60],{},[30,58,59],{},"Cost",": Infrastructure costs scaling linearly with users",[37,62,63,66],{},[30,64,65],{},"Complexity",": Managing multiple customer environments",[24,68,69],{},[30,70,71],{},"The Numbers:",[34,73,74,80,86,92,98],{},[37,75,76,79],{},[30,77,78],{},"Query Performance",": 2-5 seconds (vs 100ms target)",[37,81,82,85],{},[30,83,84],{},"User Capacity",": 1,000 users max (vs 100,000+ needed)",[37,87,88,91],{},[30,89,90],{},"Infrastructure Cost",": €5,000\u002Fmonth (vs €500\u002Fmonth target)",[37,93,94,97],{},[30,95,96],{},"Uptime",": 95% (vs 99.9% required)",[37,99,100,103],{},[30,101,102],{},"Development Time",": 80% spent on scalability fixes",[24,105,106],{},[107,108],"img",{"alt":109,"className":110,"height":112,"src":113,"width":114},"SaaS architecture challenges",[111],"rounded-lg",600,"https:\u002F\u002Fpicsum.photos\u002Fid\u002F17\u002F1000\u002F600",1000,[19,116,118],{"id":117},"the-solution-proven-saas-architecture-patterns","The Solution: Proven SaaS Architecture Patterns",[120,121,123],"h3",{"id":122},"our-approach-multi-tenant-architecture-with-performance-optimization","Our Approach: Multi-Tenant Architecture with Performance Optimization",[24,125,126],{},"We developed a comprehensive SaaS architecture that scales from startup to enterprise:",[24,128,129],{},[30,130,131],{},"Key Patterns:",[34,133,134,140,146,152,158],{},[37,135,136,139],{},[30,137,138],{},"Multi-Tenant Database Design",": Efficient data isolation and sharing",[37,141,142,145],{},[30,143,144],{},"API-First Architecture",": Scalable API design patterns",[37,147,148,151],{},[30,149,150],{},"Caching Strategy",": Multi-layer caching for performance",[37,153,154,157],{},[30,155,156],{},"Microservices Architecture",": Modular, scalable service design",[37,159,160,163],{},[30,161,162],{},"Performance Optimization",": Database and application optimization",[19,165,167],{"id":166},"multi-tenant-database-architecture","Multi-Tenant Database Architecture",[120,169,171],{"id":170},"_1-database-design-patterns","1. Database Design Patterns",[24,173,174],{},"We implemented efficient multi-tenant database patterns:",[176,177,182],"pre",{"className":178,"code":179,"language":180,"meta":181,"style":181},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","-- Pattern 1: Shared Database, Shared Schema\n-- All tenants share the same database and schema\nCREATE TABLE tenants (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    name VARCHAR(255) NOT NULL,\n    subdomain VARCHAR(100) UNIQUE NOT NULL,\n    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n);\n\nCREATE TABLE users (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,\n    email VARCHAR(255) NOT NULL,\n    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),\n    UNIQUE(tenant_id, email)\n);\n\n-- Optimized indexes for multi-tenant queries\nCREATE INDEX CONCURRENTLY idx_users_tenant_email ON users (tenant_id, email);\nCREATE INDEX CONCURRENTLY idx_users_tenant_created ON users (tenant_id, created_at);\n\n-- Pattern 2: Shared Database, Separate Schema\n-- Each tenant gets their own schema\nCREATE SCHEMA tenant_001;\nCREATE SCHEMA tenant_002;\n\n-- Pattern 3: Separate Database\n-- Each tenant gets their own database\n-- tenant_001_db, tenant_002_db, etc.\n","sql","",[183,184,185,193,199,205,211,217,223,229,235,242,248,253,259,265,271,277,282,287,293,299,305,310,316,322,328,334,339,345,351],"code",{"__ignoreMap":181},[186,187,190],"span",{"class":188,"line":189},"line",1,[186,191,192],{},"-- Pattern 1: Shared Database, Shared Schema\n",[186,194,196],{"class":188,"line":195},2,[186,197,198],{},"-- All tenants share the same database and schema\n",[186,200,202],{"class":188,"line":201},3,[186,203,204],{},"CREATE TABLE tenants (\n",[186,206,208],{"class":188,"line":207},4,[186,209,210],{},"    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n",[186,212,214],{"class":188,"line":213},5,[186,215,216],{},"    name VARCHAR(255) NOT NULL,\n",[186,218,220],{"class":188,"line":219},6,[186,221,222],{},"    subdomain VARCHAR(100) UNIQUE NOT NULL,\n",[186,224,226],{"class":188,"line":225},7,[186,227,228],{},"    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n",[186,230,232],{"class":188,"line":231},8,[186,233,234],{},");\n",[186,236,238],{"class":188,"line":237},9,[186,239,241],{"emptyLinePlaceholder":240},true,"\n",[186,243,245],{"class":188,"line":244},10,[186,246,247],{},"CREATE TABLE users (\n",[186,249,251],{"class":188,"line":250},11,[186,252,210],{},[186,254,256],{"class":188,"line":255},12,[186,257,258],{},"    tenant_id UUID REFERENCES tenants(id) ON DELETE CASCADE,\n",[186,260,262],{"class":188,"line":261},13,[186,263,264],{},"    email VARCHAR(255) NOT NULL,\n",[186,266,268],{"class":188,"line":267},14,[186,269,270],{},"    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),\n",[186,272,274],{"class":188,"line":273},15,[186,275,276],{},"    UNIQUE(tenant_id, email)\n",[186,278,280],{"class":188,"line":279},16,[186,281,234],{},[186,283,285],{"class":188,"line":284},17,[186,286,241],{"emptyLinePlaceholder":240},[186,288,290],{"class":188,"line":289},18,[186,291,292],{},"-- Optimized indexes for multi-tenant queries\n",[186,294,296],{"class":188,"line":295},19,[186,297,298],{},"CREATE INDEX CONCURRENTLY idx_users_tenant_email ON users (tenant_id, email);\n",[186,300,302],{"class":188,"line":301},20,[186,303,304],{},"CREATE INDEX CONCURRENTLY idx_users_tenant_created ON users (tenant_id, created_at);\n",[186,306,308],{"class":188,"line":307},21,[186,309,241],{"emptyLinePlaceholder":240},[186,311,313],{"class":188,"line":312},22,[186,314,315],{},"-- Pattern 2: Shared Database, Separate Schema\n",[186,317,319],{"class":188,"line":318},23,[186,320,321],{},"-- Each tenant gets their own schema\n",[186,323,325],{"class":188,"line":324},24,[186,326,327],{},"CREATE SCHEMA tenant_001;\n",[186,329,331],{"class":188,"line":330},25,[186,332,333],{},"CREATE SCHEMA tenant_002;\n",[186,335,337],{"class":188,"line":336},26,[186,338,241],{"emptyLinePlaceholder":240},[186,340,342],{"class":188,"line":341},27,[186,343,344],{},"-- Pattern 3: Separate Database\n",[186,346,348],{"class":188,"line":347},28,[186,349,350],{},"-- Each tenant gets their own database\n",[186,352,354],{"class":188,"line":353},29,[186,355,356],{},"-- tenant_001_db, tenant_002_db, etc.\n",[24,358,359],{},[30,360,361],{},"Why This Works:",[34,363,364,370,375,380],{},[37,365,366,369],{},[30,367,368],{},"Data Isolation",": Clear separation between tenant data",[37,371,372,374],{},[30,373,47],{},": Optimized indexes for multi-tenant queries",[37,376,377,379],{},[30,378,53],{},": Can handle thousands of tenants",[37,381,382,385],{},[30,383,384],{},"Cost Efficiency",": Shared infrastructure reduces costs",[24,387,388,391],{},[30,389,390],{},"Result:"," Query performance improved by 90%, tenant capacity increased to 100,000+",[120,393,395],{"id":394},"_2-tenant-resolution-strategy","2. Tenant Resolution Strategy",[24,397,398],{},"We implemented efficient tenant resolution:",[176,400,404],{"className":401,"code":402,"language":403,"meta":181,"style":181},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Tenant resolution middleware\nexport class TenantResolver {\n  private cache: Map\u003Cstring, TenantInfo>;\n  private db: Database;\n  \n  constructor() {\n    this.cache = new Map();\n    this.db = new Database();\n  }\n  \n  \u002F\u002F Resolve tenant from subdomain\n  async resolveTenant(subdomain: string): Promise\u003CTenantInfo> {\n    \u002F\u002F Check cache first\n    const cached = this.cache.get(subdomain);\n    if (cached) {\n      return cached;\n    }\n    \n    \u002F\u002F Query database\n    const tenant = await this.db.query(\n      'SELECT id, name, subdomain, settings FROM tenants WHERE subdomain = $1',\n      [subdomain]\n    );\n    \n    if (tenant.rows.length === 0) {\n      throw new Error('Tenant not found');\n    }\n    \n    const tenantInfo: TenantInfo = {\n      id: tenant.rows[0].id,\n      name: tenant.rows[0].name,\n      subdomain: tenant.rows[0].subdomain,\n      settings: tenant.rows[0].settings\n    };\n    \n    \u002F\u002F Cache for 5 minutes\n    this.cache.set(subdomain, tenantInfo);\n    setTimeout(() => this.cache.delete(subdomain), 5 * 60 * 1000);\n    \n    return tenantInfo;\n  }\n  \n  \u002F\u002F Resolve tenant from JWT token\n  async resolveTenantFromToken(token: string): Promise\u003CTenantInfo> {\n    const decoded = jwt.verify(token, process.env.JWT_SECRET);\n    return this.resolveTenant(decoded.subdomain);\n  }\n  \n  \u002F\u002F Middleware for automatic tenant resolution\n  middleware() {\n    return async (req: Request, res: Response, next: NextFunction) => {\n      try {\n        const subdomain = req.headers.host?.split('.')[0];\n        const tenant = await this.resolveTenant(subdomain);\n        req.tenant = tenant;\n        next();\n      } catch (error) {\n        res.status(404).json({ error: 'Tenant not found' });\n      }\n    };\n  }\n}\n","typescript",[183,405,406,412,430,460,475,481,491,512,529,534,538,543,579,584,614,631,640,645,650,655,679,694,704,711,715,745,768,772,776,791,821,848,874,899,905,910,916,940,988,993,1003,1008,1013,1019,1048,1089,1112,1117,1122,1128,1138,1182,1190,1237,1260,1276,1286,1304,1351,1357,1362,1367],{"__ignoreMap":181},[186,407,408],{"class":188,"line":189},[186,409,411],{"class":410},"sHwdD","\u002F\u002F Tenant resolution middleware\n",[186,413,414,418,422,426],{"class":188,"line":195},[186,415,417],{"class":416},"s7zQu","export",[186,419,421],{"class":420},"spNyl"," class",[186,423,425],{"class":424},"sBMFI"," TenantResolver",[186,427,429],{"class":428},"sMK4o"," {\n",[186,431,432,435,439,442,445,448,451,454,457],{"class":188,"line":201},[186,433,434],{"class":420},"  private",[186,436,438],{"class":437},"swJcz"," cache",[186,440,441],{"class":428},":",[186,443,444],{"class":424}," Map",[186,446,447],{"class":428},"\u003C",[186,449,450],{"class":424},"string",[186,452,453],{"class":428},",",[186,455,456],{"class":424}," TenantInfo",[186,458,459],{"class":428},">;\n",[186,461,462,464,467,469,472],{"class":188,"line":207},[186,463,434],{"class":420},[186,465,466],{"class":437}," db",[186,468,441],{"class":428},[186,470,471],{"class":424}," Database",[186,473,474],{"class":428},";\n",[186,476,477],{"class":188,"line":213},[186,478,480],{"class":479},"sTEyZ","  \n",[186,482,483,486,489],{"class":188,"line":219},[186,484,485],{"class":420},"  constructor",[186,487,488],{"class":428},"()",[186,490,429],{"class":428},[186,492,493,496,499,502,505,508,510],{"class":188,"line":225},[186,494,495],{"class":428},"    this.",[186,497,498],{"class":479},"cache",[186,500,501],{"class":428}," =",[186,503,504],{"class":428}," new",[186,506,444],{"class":507},"s2Zo4",[186,509,488],{"class":437},[186,511,474],{"class":428},[186,513,514,516,519,521,523,525,527],{"class":188,"line":231},[186,515,495],{"class":428},[186,517,518],{"class":479},"db",[186,520,501],{"class":428},[186,522,504],{"class":428},[186,524,471],{"class":507},[186,526,488],{"class":437},[186,528,474],{"class":428},[186,530,531],{"class":188,"line":237},[186,532,533],{"class":428},"  }\n",[186,535,536],{"class":188,"line":244},[186,537,480],{"class":479},[186,539,540],{"class":188,"line":250},[186,541,542],{"class":410},"  \u002F\u002F Resolve tenant from subdomain\n",[186,544,545,548,551,554,558,560,563,566,569,571,574,577],{"class":188,"line":255},[186,546,547],{"class":420},"  async",[186,549,550],{"class":437}," resolveTenant",[186,552,553],{"class":428},"(",[186,555,557],{"class":556},"sHdIc","subdomain",[186,559,441],{"class":428},[186,561,562],{"class":424}," string",[186,564,565],{"class":428},"):",[186,567,568],{"class":424}," Promise",[186,570,447],{"class":428},[186,572,573],{"class":424},"TenantInfo",[186,575,576],{"class":428},">",[186,578,429],{"class":428},[186,580,581],{"class":188,"line":261},[186,582,583],{"class":410},"    \u002F\u002F Check cache first\n",[186,585,586,589,592,594,597,599,602,605,607,609,612],{"class":188,"line":267},[186,587,588],{"class":420},"    const",[186,590,591],{"class":479}," cached",[186,593,501],{"class":428},[186,595,596],{"class":428}," this.",[186,598,498],{"class":479},[186,600,601],{"class":428},".",[186,603,604],{"class":507},"get",[186,606,553],{"class":437},[186,608,557],{"class":479},[186,610,611],{"class":437},")",[186,613,474],{"class":428},[186,615,616,619,622,625,628],{"class":188,"line":273},[186,617,618],{"class":416},"    if",[186,620,621],{"class":437}," (",[186,623,624],{"class":479},"cached",[186,626,627],{"class":437},") ",[186,629,630],{"class":428},"{\n",[186,632,633,636,638],{"class":188,"line":279},[186,634,635],{"class":416},"      return",[186,637,591],{"class":479},[186,639,474],{"class":428},[186,641,642],{"class":188,"line":284},[186,643,644],{"class":428},"    }\n",[186,646,647],{"class":188,"line":289},[186,648,649],{"class":437},"    \n",[186,651,652],{"class":188,"line":295},[186,653,654],{"class":410},"    \u002F\u002F Query database\n",[186,656,657,659,662,664,667,669,671,673,676],{"class":188,"line":301},[186,658,588],{"class":420},[186,660,661],{"class":479}," tenant",[186,663,501],{"class":428},[186,665,666],{"class":416}," await",[186,668,596],{"class":428},[186,670,518],{"class":479},[186,672,601],{"class":428},[186,674,675],{"class":507},"query",[186,677,678],{"class":437},"(\n",[186,680,681,684,688,691],{"class":188,"line":307},[186,682,683],{"class":428},"      '",[186,685,687],{"class":686},"sfazB","SELECT id, name, subdomain, settings FROM tenants WHERE subdomain = $1",[186,689,690],{"class":428},"'",[186,692,693],{"class":428},",\n",[186,695,696,699,701],{"class":188,"line":312},[186,697,698],{"class":437},"      [",[186,700,557],{"class":479},[186,702,703],{"class":437},"]\n",[186,705,706,709],{"class":188,"line":318},[186,707,708],{"class":437},"    )",[186,710,474],{"class":428},[186,712,713],{"class":188,"line":324},[186,714,649],{"class":437},[186,716,717,719,721,724,726,729,731,734,737,741,743],{"class":188,"line":330},[186,718,618],{"class":416},[186,720,621],{"class":437},[186,722,723],{"class":479},"tenant",[186,725,601],{"class":428},[186,727,728],{"class":479},"rows",[186,730,601],{"class":428},[186,732,733],{"class":479},"length",[186,735,736],{"class":428}," ===",[186,738,740],{"class":739},"sbssI"," 0",[186,742,627],{"class":437},[186,744,630],{"class":428},[186,746,747,750,752,755,757,759,762,764,766],{"class":188,"line":336},[186,748,749],{"class":416},"      throw",[186,751,504],{"class":428},[186,753,754],{"class":507}," Error",[186,756,553],{"class":437},[186,758,690],{"class":428},[186,760,761],{"class":686},"Tenant not found",[186,763,690],{"class":428},[186,765,611],{"class":437},[186,767,474],{"class":428},[186,769,770],{"class":188,"line":341},[186,771,644],{"class":428},[186,773,774],{"class":188,"line":347},[186,775,649],{"class":437},[186,777,778,780,783,785,787,789],{"class":188,"line":353},[186,779,588],{"class":420},[186,781,782],{"class":479}," tenantInfo",[186,784,441],{"class":428},[186,786,456],{"class":424},[186,788,501],{"class":428},[186,790,429],{"class":428},[186,792,794,797,799,801,803,805,808,811,814,816,819],{"class":188,"line":793},30,[186,795,796],{"class":437},"      id",[186,798,441],{"class":428},[186,800,661],{"class":479},[186,802,601],{"class":428},[186,804,728],{"class":479},[186,806,807],{"class":437},"[",[186,809,810],{"class":739},"0",[186,812,813],{"class":437},"]",[186,815,601],{"class":428},[186,817,818],{"class":479},"id",[186,820,693],{"class":428},[186,822,824,827,829,831,833,835,837,839,841,843,846],{"class":188,"line":823},31,[186,825,826],{"class":437},"      name",[186,828,441],{"class":428},[186,830,661],{"class":479},[186,832,601],{"class":428},[186,834,728],{"class":479},[186,836,807],{"class":437},[186,838,810],{"class":739},[186,840,813],{"class":437},[186,842,601],{"class":428},[186,844,845],{"class":479},"name",[186,847,693],{"class":428},[186,849,851,854,856,858,860,862,864,866,868,870,872],{"class":188,"line":850},32,[186,852,853],{"class":437},"      subdomain",[186,855,441],{"class":428},[186,857,661],{"class":479},[186,859,601],{"class":428},[186,861,728],{"class":479},[186,863,807],{"class":437},[186,865,810],{"class":739},[186,867,813],{"class":437},[186,869,601],{"class":428},[186,871,557],{"class":479},[186,873,693],{"class":428},[186,875,877,880,882,884,886,888,890,892,894,896],{"class":188,"line":876},33,[186,878,879],{"class":437},"      settings",[186,881,441],{"class":428},[186,883,661],{"class":479},[186,885,601],{"class":428},[186,887,728],{"class":479},[186,889,807],{"class":437},[186,891,810],{"class":739},[186,893,813],{"class":437},[186,895,601],{"class":428},[186,897,898],{"class":479},"settings\n",[186,900,902],{"class":188,"line":901},34,[186,903,904],{"class":428},"    };\n",[186,906,908],{"class":188,"line":907},35,[186,909,649],{"class":437},[186,911,913],{"class":188,"line":912},36,[186,914,915],{"class":410},"    \u002F\u002F Cache for 5 minutes\n",[186,917,919,921,923,925,928,930,932,934,936,938],{"class":188,"line":918},37,[186,920,495],{"class":428},[186,922,498],{"class":479},[186,924,601],{"class":428},[186,926,927],{"class":507},"set",[186,929,553],{"class":437},[186,931,557],{"class":479},[186,933,453],{"class":428},[186,935,782],{"class":479},[186,937,611],{"class":437},[186,939,474],{"class":428},[186,941,943,946,948,950,953,955,957,959,962,964,966,968,970,973,976,979,981,984,986],{"class":188,"line":942},38,[186,944,945],{"class":507},"    setTimeout",[186,947,553],{"class":437},[186,949,488],{"class":428},[186,951,952],{"class":420}," =>",[186,954,596],{"class":428},[186,956,498],{"class":479},[186,958,601],{"class":428},[186,960,961],{"class":507},"delete",[186,963,553],{"class":437},[186,965,557],{"class":479},[186,967,611],{"class":437},[186,969,453],{"class":428},[186,971,972],{"class":739}," 5",[186,974,975],{"class":428}," *",[186,977,978],{"class":739}," 60",[186,980,975],{"class":428},[186,982,983],{"class":739}," 1000",[186,985,611],{"class":437},[186,987,474],{"class":428},[186,989,991],{"class":188,"line":990},39,[186,992,649],{"class":437},[186,994,996,999,1001],{"class":188,"line":995},40,[186,997,998],{"class":416},"    return",[186,1000,782],{"class":479},[186,1002,474],{"class":428},[186,1004,1006],{"class":188,"line":1005},41,[186,1007,533],{"class":428},[186,1009,1011],{"class":188,"line":1010},42,[186,1012,480],{"class":479},[186,1014,1016],{"class":188,"line":1015},43,[186,1017,1018],{"class":410},"  \u002F\u002F Resolve tenant from JWT token\n",[186,1020,1022,1024,1027,1029,1032,1034,1036,1038,1040,1042,1044,1046],{"class":188,"line":1021},44,[186,1023,547],{"class":420},[186,1025,1026],{"class":437}," resolveTenantFromToken",[186,1028,553],{"class":428},[186,1030,1031],{"class":556},"token",[186,1033,441],{"class":428},[186,1035,562],{"class":424},[186,1037,565],{"class":428},[186,1039,568],{"class":424},[186,1041,447],{"class":428},[186,1043,573],{"class":424},[186,1045,576],{"class":428},[186,1047,429],{"class":428},[186,1049,1051,1053,1056,1058,1061,1063,1066,1068,1070,1072,1075,1077,1080,1082,1085,1087],{"class":188,"line":1050},45,[186,1052,588],{"class":420},[186,1054,1055],{"class":479}," decoded",[186,1057,501],{"class":428},[186,1059,1060],{"class":479}," jwt",[186,1062,601],{"class":428},[186,1064,1065],{"class":507},"verify",[186,1067,553],{"class":437},[186,1069,1031],{"class":479},[186,1071,453],{"class":428},[186,1073,1074],{"class":479}," process",[186,1076,601],{"class":428},[186,1078,1079],{"class":479},"env",[186,1081,601],{"class":428},[186,1083,1084],{"class":479},"JWT_SECRET",[186,1086,611],{"class":437},[186,1088,474],{"class":428},[186,1090,1092,1094,1096,1099,1101,1104,1106,1108,1110],{"class":188,"line":1091},46,[186,1093,998],{"class":416},[186,1095,596],{"class":428},[186,1097,1098],{"class":507},"resolveTenant",[186,1100,553],{"class":437},[186,1102,1103],{"class":479},"decoded",[186,1105,601],{"class":428},[186,1107,557],{"class":479},[186,1109,611],{"class":437},[186,1111,474],{"class":428},[186,1113,1115],{"class":188,"line":1114},47,[186,1116,533],{"class":428},[186,1118,1120],{"class":188,"line":1119},48,[186,1121,480],{"class":479},[186,1123,1125],{"class":188,"line":1124},49,[186,1126,1127],{"class":410},"  \u002F\u002F Middleware for automatic tenant resolution\n",[186,1129,1131,1134,1136],{"class":188,"line":1130},50,[186,1132,1133],{"class":437},"  middleware",[186,1135,488],{"class":428},[186,1137,429],{"class":428},[186,1139,1141,1143,1146,1148,1151,1153,1156,1158,1161,1163,1166,1168,1171,1173,1176,1178,1180],{"class":188,"line":1140},51,[186,1142,998],{"class":416},[186,1144,1145],{"class":420}," async",[186,1147,621],{"class":428},[186,1149,1150],{"class":556},"req",[186,1152,441],{"class":428},[186,1154,1155],{"class":424}," Request",[186,1157,453],{"class":428},[186,1159,1160],{"class":556}," res",[186,1162,441],{"class":428},[186,1164,1165],{"class":424}," Response",[186,1167,453],{"class":428},[186,1169,1170],{"class":556}," next",[186,1172,441],{"class":428},[186,1174,1175],{"class":424}," NextFunction",[186,1177,611],{"class":428},[186,1179,952],{"class":420},[186,1181,429],{"class":428},[186,1183,1185,1188],{"class":188,"line":1184},52,[186,1186,1187],{"class":416},"      try",[186,1189,429],{"class":428},[186,1191,1193,1196,1199,1201,1204,1206,1209,1211,1214,1217,1220,1222,1224,1226,1228,1231,1233,1235],{"class":188,"line":1192},53,[186,1194,1195],{"class":420},"        const",[186,1197,1198],{"class":479}," subdomain",[186,1200,501],{"class":428},[186,1202,1203],{"class":479}," req",[186,1205,601],{"class":428},[186,1207,1208],{"class":479},"headers",[186,1210,601],{"class":428},[186,1212,1213],{"class":479},"host",[186,1215,1216],{"class":428},"?.",[186,1218,1219],{"class":507},"split",[186,1221,553],{"class":437},[186,1223,690],{"class":428},[186,1225,601],{"class":686},[186,1227,690],{"class":428},[186,1229,1230],{"class":437},")[",[186,1232,810],{"class":739},[186,1234,813],{"class":437},[186,1236,474],{"class":428},[186,1238,1240,1242,1244,1246,1248,1250,1252,1254,1256,1258],{"class":188,"line":1239},54,[186,1241,1195],{"class":420},[186,1243,661],{"class":479},[186,1245,501],{"class":428},[186,1247,666],{"class":416},[186,1249,596],{"class":428},[186,1251,1098],{"class":507},[186,1253,553],{"class":437},[186,1255,557],{"class":479},[186,1257,611],{"class":437},[186,1259,474],{"class":428},[186,1261,1263,1266,1268,1270,1272,1274],{"class":188,"line":1262},55,[186,1264,1265],{"class":479},"        req",[186,1267,601],{"class":428},[186,1269,723],{"class":479},[186,1271,501],{"class":428},[186,1273,661],{"class":479},[186,1275,474],{"class":428},[186,1277,1279,1282,1284],{"class":188,"line":1278},56,[186,1280,1281],{"class":507},"        next",[186,1283,488],{"class":437},[186,1285,474],{"class":428},[186,1287,1289,1292,1295,1297,1300,1302],{"class":188,"line":1288},57,[186,1290,1291],{"class":428},"      }",[186,1293,1294],{"class":416}," catch",[186,1296,621],{"class":437},[186,1298,1299],{"class":479},"error",[186,1301,627],{"class":437},[186,1303,630],{"class":428},[186,1305,1307,1310,1312,1315,1317,1320,1322,1324,1327,1329,1332,1335,1337,1340,1342,1344,1347,1349],{"class":188,"line":1306},58,[186,1308,1309],{"class":479},"        res",[186,1311,601],{"class":428},[186,1313,1314],{"class":507},"status",[186,1316,553],{"class":437},[186,1318,1319],{"class":739},"404",[186,1321,611],{"class":437},[186,1323,601],{"class":428},[186,1325,1326],{"class":507},"json",[186,1328,553],{"class":437},[186,1330,1331],{"class":428},"{",[186,1333,1334],{"class":437}," error",[186,1336,441],{"class":428},[186,1338,1339],{"class":428}," '",[186,1341,761],{"class":686},[186,1343,690],{"class":428},[186,1345,1346],{"class":428}," }",[186,1348,611],{"class":437},[186,1350,474],{"class":428},[186,1352,1354],{"class":188,"line":1353},59,[186,1355,1356],{"class":428},"      }\n",[186,1358,1360],{"class":188,"line":1359},60,[186,1361,904],{"class":428},[186,1363,1365],{"class":188,"line":1364},61,[186,1366,533],{"class":428},[186,1368,1370],{"class":188,"line":1369},62,[186,1371,1372],{"class":428},"}\n",[24,1374,1375],{},[30,1376,361],{},[34,1378,1379,1385,1391,1397],{},[37,1380,1381,1384],{},[30,1382,1383],{},"Fast Resolution",": Cached tenant lookup in \u003C10ms",[37,1386,1387,1390],{},[30,1388,1389],{},"Automatic Middleware",": Transparent tenant resolution",[37,1392,1393,1396],{},[30,1394,1395],{},"Error Handling",": Graceful handling of invalid tenants",[37,1398,1399,1401],{},[30,1400,53],{},": Can handle thousands of concurrent requests",[24,1403,1404,1406],{},[30,1405,390],{}," Tenant resolution time reduced from 200ms to 10ms (95% improvement)",[19,1408,1410],{"id":1409},"api-architecture-patterns","API Architecture Patterns",[120,1412,1414],{"id":1413},"_1-restful-api-design","1. RESTful API Design",[24,1416,1417],{},"We implemented scalable RESTful API patterns:",[176,1419,1421],{"className":401,"code":1420,"language":403,"meta":181,"style":181},"\u002F\u002F Multi-tenant API controller\nexport class TenantController {\n  private db: Database;\n  private cache: Cache;\n  \n  constructor() {\n    this.db = new Database();\n    this.cache = new Cache();\n  }\n  \n  \u002F\u002F Get tenant-specific data\n  async getUsers(req: Request, res: Response): Promise\u003Cvoid> {\n    const { tenant } = req;\n    const { page = 1, limit = 20 } = req.query;\n    \n    try {\n      \u002F\u002F Check cache first\n      const cacheKey = `users:${tenant.id}:${page}:${limit}`;\n      const cached = await this.cache.get(cacheKey);\n      if (cached) {\n        res.json(cached);\n        return;\n      }\n      \n      \u002F\u002F Query database with tenant isolation\n      const users = await this.db.query(\n        'SELECT id, email, created_at FROM users WHERE tenant_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3',\n        [tenant.id, limit, (page - 1) * limit]\n      );\n      \n      const result = {\n        users: users.rows,\n        pagination: {\n          page: parseInt(page as string),\n          limit: parseInt(limit as string),\n          total: await this.getUserCount(tenant.id)\n        }\n      };\n      \n      \u002F\u002F Cache for 5 minutes\n      await this.cache.set(cacheKey, result, 300);\n      \n      res.json(result);\n      \n    } catch (error) {\n      res.status(500).json({ error: 'Internal server error' });\n    }\n  }\n  \n  \u002F\u002F Create tenant-specific resource\n  async createUser(req: Request, res: Response): Promise\u003Cvoid> {\n    const { tenant } = req;\n    const { email, password } = req.body;\n    \n    try {\n      \u002F\u002F Validate tenant-specific constraints\n      await this.validateUserCreation(tenant, email);\n      \n      \u002F\u002F Create user with tenant isolation\n      const user = await this.db.query(\n        'INSERT INTO users (tenant_id, email, password_hash) VALUES ($1, $2, $3) RETURNING id, email, created_at',\n        [tenant.id, email, await bcrypt.hash(password, 12)]\n      );\n      \n      \u002F\u002F Invalidate cache\n      await this.cache.deletePattern(`users:${tenant.id}:*`);\n      \n      res.status(201).json(user.rows[0]);\n      \n    } catch (error) {\n      res.status(400).json({ error: error.message });\n    }\n  }\n}\n",[183,1422,1423,1428,1439,1451,1464,1468,1476,1492,1508,1512,1516,1521,1557,1574,1610,1614,1621,1626,1675,1702,1715,1731,1738,1742,1747,1752,1773,1785,1820,1827,1831,1842,1857,1866,1889,1910,1935,1940,1945,1949,1954,1984,1988,2006,2010,2025,2065,2069,2073,2077,2082,2117,2133,2160,2164,2170,2175,2196,2200,2205,2226,2237,2276,2283,2288,2294,2334,2339,2377,2382,2397,2438,2443,2448],{"__ignoreMap":181},[186,1424,1425],{"class":188,"line":189},[186,1426,1427],{"class":410},"\u002F\u002F Multi-tenant API controller\n",[186,1429,1430,1432,1434,1437],{"class":188,"line":195},[186,1431,417],{"class":416},[186,1433,421],{"class":420},[186,1435,1436],{"class":424}," TenantController",[186,1438,429],{"class":428},[186,1440,1441,1443,1445,1447,1449],{"class":188,"line":201},[186,1442,434],{"class":420},[186,1444,466],{"class":437},[186,1446,441],{"class":428},[186,1448,471],{"class":424},[186,1450,474],{"class":428},[186,1452,1453,1455,1457,1459,1462],{"class":188,"line":207},[186,1454,434],{"class":420},[186,1456,438],{"class":437},[186,1458,441],{"class":428},[186,1460,1461],{"class":424}," Cache",[186,1463,474],{"class":428},[186,1465,1466],{"class":188,"line":213},[186,1467,480],{"class":479},[186,1469,1470,1472,1474],{"class":188,"line":219},[186,1471,485],{"class":420},[186,1473,488],{"class":428},[186,1475,429],{"class":428},[186,1477,1478,1480,1482,1484,1486,1488,1490],{"class":188,"line":225},[186,1479,495],{"class":428},[186,1481,518],{"class":479},[186,1483,501],{"class":428},[186,1485,504],{"class":428},[186,1487,471],{"class":507},[186,1489,488],{"class":437},[186,1491,474],{"class":428},[186,1493,1494,1496,1498,1500,1502,1504,1506],{"class":188,"line":231},[186,1495,495],{"class":428},[186,1497,498],{"class":479},[186,1499,501],{"class":428},[186,1501,504],{"class":428},[186,1503,1461],{"class":507},[186,1505,488],{"class":437},[186,1507,474],{"class":428},[186,1509,1510],{"class":188,"line":237},[186,1511,533],{"class":428},[186,1513,1514],{"class":188,"line":244},[186,1515,480],{"class":479},[186,1517,1518],{"class":188,"line":250},[186,1519,1520],{"class":410},"  \u002F\u002F Get tenant-specific data\n",[186,1522,1523,1525,1528,1530,1532,1534,1536,1538,1540,1542,1544,1546,1548,1550,1553,1555],{"class":188,"line":255},[186,1524,547],{"class":420},[186,1526,1527],{"class":437}," getUsers",[186,1529,553],{"class":428},[186,1531,1150],{"class":556},[186,1533,441],{"class":428},[186,1535,1155],{"class":424},[186,1537,453],{"class":428},[186,1539,1160],{"class":556},[186,1541,441],{"class":428},[186,1543,1165],{"class":424},[186,1545,565],{"class":428},[186,1547,568],{"class":424},[186,1549,447],{"class":428},[186,1551,1552],{"class":424},"void",[186,1554,576],{"class":428},[186,1556,429],{"class":428},[186,1558,1559,1561,1564,1566,1568,1570,1572],{"class":188,"line":261},[186,1560,588],{"class":420},[186,1562,1563],{"class":428}," {",[186,1565,661],{"class":479},[186,1567,1346],{"class":428},[186,1569,501],{"class":428},[186,1571,1203],{"class":479},[186,1573,474],{"class":428},[186,1575,1576,1578,1580,1583,1585,1588,1590,1593,1595,1598,1600,1602,1604,1606,1608],{"class":188,"line":267},[186,1577,588],{"class":420},[186,1579,1563],{"class":428},[186,1581,1582],{"class":479}," page",[186,1584,501],{"class":428},[186,1586,1587],{"class":739}," 1",[186,1589,453],{"class":428},[186,1591,1592],{"class":479}," limit",[186,1594,501],{"class":428},[186,1596,1597],{"class":739}," 20",[186,1599,1346],{"class":428},[186,1601,501],{"class":428},[186,1603,1203],{"class":479},[186,1605,601],{"class":428},[186,1607,675],{"class":479},[186,1609,474],{"class":428},[186,1611,1612],{"class":188,"line":273},[186,1613,649],{"class":437},[186,1615,1616,1619],{"class":188,"line":279},[186,1617,1618],{"class":416},"    try",[186,1620,429],{"class":428},[186,1622,1623],{"class":188,"line":284},[186,1624,1625],{"class":410},"      \u002F\u002F Check cache first\n",[186,1627,1628,1631,1634,1636,1639,1642,1645,1647,1649,1651,1654,1656,1658,1661,1663,1665,1667,1670,1673],{"class":188,"line":289},[186,1629,1630],{"class":420},"      const",[186,1632,1633],{"class":479}," cacheKey",[186,1635,501],{"class":428},[186,1637,1638],{"class":428}," `",[186,1640,1641],{"class":686},"users:",[186,1643,1644],{"class":428},"${",[186,1646,723],{"class":479},[186,1648,601],{"class":428},[186,1650,818],{"class":479},[186,1652,1653],{"class":428},"}",[186,1655,441],{"class":686},[186,1657,1644],{"class":428},[186,1659,1660],{"class":479},"page",[186,1662,1653],{"class":428},[186,1664,441],{"class":686},[186,1666,1644],{"class":428},[186,1668,1669],{"class":479},"limit",[186,1671,1672],{"class":428},"}`",[186,1674,474],{"class":428},[186,1676,1677,1679,1681,1683,1685,1687,1689,1691,1693,1695,1698,1700],{"class":188,"line":295},[186,1678,1630],{"class":420},[186,1680,591],{"class":479},[186,1682,501],{"class":428},[186,1684,666],{"class":416},[186,1686,596],{"class":428},[186,1688,498],{"class":479},[186,1690,601],{"class":428},[186,1692,604],{"class":507},[186,1694,553],{"class":437},[186,1696,1697],{"class":479},"cacheKey",[186,1699,611],{"class":437},[186,1701,474],{"class":428},[186,1703,1704,1707,1709,1711,1713],{"class":188,"line":301},[186,1705,1706],{"class":416},"      if",[186,1708,621],{"class":437},[186,1710,624],{"class":479},[186,1712,627],{"class":437},[186,1714,630],{"class":428},[186,1716,1717,1719,1721,1723,1725,1727,1729],{"class":188,"line":307},[186,1718,1309],{"class":479},[186,1720,601],{"class":428},[186,1722,1326],{"class":507},[186,1724,553],{"class":437},[186,1726,624],{"class":479},[186,1728,611],{"class":437},[186,1730,474],{"class":428},[186,1732,1733,1736],{"class":188,"line":312},[186,1734,1735],{"class":416},"        return",[186,1737,474],{"class":428},[186,1739,1740],{"class":188,"line":318},[186,1741,1356],{"class":428},[186,1743,1744],{"class":188,"line":324},[186,1745,1746],{"class":437},"      \n",[186,1748,1749],{"class":188,"line":330},[186,1750,1751],{"class":410},"      \u002F\u002F Query database with tenant isolation\n",[186,1753,1754,1756,1759,1761,1763,1765,1767,1769,1771],{"class":188,"line":336},[186,1755,1630],{"class":420},[186,1757,1758],{"class":479}," users",[186,1760,501],{"class":428},[186,1762,666],{"class":416},[186,1764,596],{"class":428},[186,1766,518],{"class":479},[186,1768,601],{"class":428},[186,1770,675],{"class":507},[186,1772,678],{"class":437},[186,1774,1775,1778,1781,1783],{"class":188,"line":341},[186,1776,1777],{"class":428},"        '",[186,1779,1780],{"class":686},"SELECT id, email, created_at FROM users WHERE tenant_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3",[186,1782,690],{"class":428},[186,1784,693],{"class":428},[186,1786,1787,1790,1792,1794,1796,1798,1800,1802,1804,1806,1809,1811,1813,1816,1818],{"class":188,"line":347},[186,1788,1789],{"class":437},"        [",[186,1791,723],{"class":479},[186,1793,601],{"class":428},[186,1795,818],{"class":479},[186,1797,453],{"class":428},[186,1799,1592],{"class":479},[186,1801,453],{"class":428},[186,1803,621],{"class":437},[186,1805,1660],{"class":479},[186,1807,1808],{"class":428}," -",[186,1810,1587],{"class":739},[186,1812,627],{"class":437},[186,1814,1815],{"class":428},"*",[186,1817,1592],{"class":479},[186,1819,703],{"class":437},[186,1821,1822,1825],{"class":188,"line":353},[186,1823,1824],{"class":437},"      )",[186,1826,474],{"class":428},[186,1828,1829],{"class":188,"line":793},[186,1830,1746],{"class":437},[186,1832,1833,1835,1838,1840],{"class":188,"line":823},[186,1834,1630],{"class":420},[186,1836,1837],{"class":479}," result",[186,1839,501],{"class":428},[186,1841,429],{"class":428},[186,1843,1844,1847,1849,1851,1853,1855],{"class":188,"line":850},[186,1845,1846],{"class":437},"        users",[186,1848,441],{"class":428},[186,1850,1758],{"class":479},[186,1852,601],{"class":428},[186,1854,728],{"class":479},[186,1856,693],{"class":428},[186,1858,1859,1862,1864],{"class":188,"line":876},[186,1860,1861],{"class":437},"        pagination",[186,1863,441],{"class":428},[186,1865,429],{"class":428},[186,1867,1868,1871,1873,1876,1878,1880,1883,1885,1887],{"class":188,"line":901},[186,1869,1870],{"class":437},"          page",[186,1872,441],{"class":428},[186,1874,1875],{"class":507}," parseInt",[186,1877,553],{"class":437},[186,1879,1660],{"class":479},[186,1881,1882],{"class":416}," as",[186,1884,562],{"class":424},[186,1886,611],{"class":437},[186,1888,693],{"class":428},[186,1890,1891,1894,1896,1898,1900,1902,1904,1906,1908],{"class":188,"line":907},[186,1892,1893],{"class":437},"          limit",[186,1895,441],{"class":428},[186,1897,1875],{"class":507},[186,1899,553],{"class":437},[186,1901,1669],{"class":479},[186,1903,1882],{"class":416},[186,1905,562],{"class":424},[186,1907,611],{"class":437},[186,1909,693],{"class":428},[186,1911,1912,1915,1917,1919,1921,1924,1926,1928,1930,1932],{"class":188,"line":912},[186,1913,1914],{"class":437},"          total",[186,1916,441],{"class":428},[186,1918,666],{"class":416},[186,1920,596],{"class":428},[186,1922,1923],{"class":507},"getUserCount",[186,1925,553],{"class":437},[186,1927,723],{"class":479},[186,1929,601],{"class":428},[186,1931,818],{"class":479},[186,1933,1934],{"class":437},")\n",[186,1936,1937],{"class":188,"line":918},[186,1938,1939],{"class":428},"        }\n",[186,1941,1942],{"class":188,"line":942},[186,1943,1944],{"class":428},"      };\n",[186,1946,1947],{"class":188,"line":990},[186,1948,1746],{"class":437},[186,1950,1951],{"class":188,"line":995},[186,1952,1953],{"class":410},"      \u002F\u002F Cache for 5 minutes\n",[186,1955,1956,1959,1961,1963,1965,1967,1969,1971,1973,1975,1977,1980,1982],{"class":188,"line":1005},[186,1957,1958],{"class":416},"      await",[186,1960,596],{"class":428},[186,1962,498],{"class":479},[186,1964,601],{"class":428},[186,1966,927],{"class":507},[186,1968,553],{"class":437},[186,1970,1697],{"class":479},[186,1972,453],{"class":428},[186,1974,1837],{"class":479},[186,1976,453],{"class":428},[186,1978,1979],{"class":739}," 300",[186,1981,611],{"class":437},[186,1983,474],{"class":428},[186,1985,1986],{"class":188,"line":1010},[186,1987,1746],{"class":437},[186,1989,1990,1993,1995,1997,1999,2002,2004],{"class":188,"line":1015},[186,1991,1992],{"class":479},"      res",[186,1994,601],{"class":428},[186,1996,1326],{"class":507},[186,1998,553],{"class":437},[186,2000,2001],{"class":479},"result",[186,2003,611],{"class":437},[186,2005,474],{"class":428},[186,2007,2008],{"class":188,"line":1021},[186,2009,1746],{"class":437},[186,2011,2012,2015,2017,2019,2021,2023],{"class":188,"line":1050},[186,2013,2014],{"class":428},"    }",[186,2016,1294],{"class":416},[186,2018,621],{"class":437},[186,2020,1299],{"class":479},[186,2022,627],{"class":437},[186,2024,630],{"class":428},[186,2026,2027,2029,2031,2033,2035,2038,2040,2042,2044,2046,2048,2050,2052,2054,2057,2059,2061,2063],{"class":188,"line":1091},[186,2028,1992],{"class":479},[186,2030,601],{"class":428},[186,2032,1314],{"class":507},[186,2034,553],{"class":437},[186,2036,2037],{"class":739},"500",[186,2039,611],{"class":437},[186,2041,601],{"class":428},[186,2043,1326],{"class":507},[186,2045,553],{"class":437},[186,2047,1331],{"class":428},[186,2049,1334],{"class":437},[186,2051,441],{"class":428},[186,2053,1339],{"class":428},[186,2055,2056],{"class":686},"Internal server error",[186,2058,690],{"class":428},[186,2060,1346],{"class":428},[186,2062,611],{"class":437},[186,2064,474],{"class":428},[186,2066,2067],{"class":188,"line":1114},[186,2068,644],{"class":428},[186,2070,2071],{"class":188,"line":1119},[186,2072,533],{"class":428},[186,2074,2075],{"class":188,"line":1124},[186,2076,480],{"class":479},[186,2078,2079],{"class":188,"line":1130},[186,2080,2081],{"class":410},"  \u002F\u002F Create tenant-specific resource\n",[186,2083,2084,2086,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111,2113,2115],{"class":188,"line":1140},[186,2085,547],{"class":420},[186,2087,2088],{"class":437}," createUser",[186,2090,553],{"class":428},[186,2092,1150],{"class":556},[186,2094,441],{"class":428},[186,2096,1155],{"class":424},[186,2098,453],{"class":428},[186,2100,1160],{"class":556},[186,2102,441],{"class":428},[186,2104,1165],{"class":424},[186,2106,565],{"class":428},[186,2108,568],{"class":424},[186,2110,447],{"class":428},[186,2112,1552],{"class":424},[186,2114,576],{"class":428},[186,2116,429],{"class":428},[186,2118,2119,2121,2123,2125,2127,2129,2131],{"class":188,"line":1184},[186,2120,588],{"class":420},[186,2122,1563],{"class":428},[186,2124,661],{"class":479},[186,2126,1346],{"class":428},[186,2128,501],{"class":428},[186,2130,1203],{"class":479},[186,2132,474],{"class":428},[186,2134,2135,2137,2139,2142,2144,2147,2149,2151,2153,2155,2158],{"class":188,"line":1192},[186,2136,588],{"class":420},[186,2138,1563],{"class":428},[186,2140,2141],{"class":479}," email",[186,2143,453],{"class":428},[186,2145,2146],{"class":479}," password",[186,2148,1346],{"class":428},[186,2150,501],{"class":428},[186,2152,1203],{"class":479},[186,2154,601],{"class":428},[186,2156,2157],{"class":479},"body",[186,2159,474],{"class":428},[186,2161,2162],{"class":188,"line":1239},[186,2163,649],{"class":437},[186,2165,2166,2168],{"class":188,"line":1262},[186,2167,1618],{"class":416},[186,2169,429],{"class":428},[186,2171,2172],{"class":188,"line":1278},[186,2173,2174],{"class":410},"      \u002F\u002F Validate tenant-specific constraints\n",[186,2176,2177,2179,2181,2184,2186,2188,2190,2192,2194],{"class":188,"line":1288},[186,2178,1958],{"class":416},[186,2180,596],{"class":428},[186,2182,2183],{"class":507},"validateUserCreation",[186,2185,553],{"class":437},[186,2187,723],{"class":479},[186,2189,453],{"class":428},[186,2191,2141],{"class":479},[186,2193,611],{"class":437},[186,2195,474],{"class":428},[186,2197,2198],{"class":188,"line":1306},[186,2199,1746],{"class":437},[186,2201,2202],{"class":188,"line":1353},[186,2203,2204],{"class":410},"      \u002F\u002F Create user with tenant isolation\n",[186,2206,2207,2209,2212,2214,2216,2218,2220,2222,2224],{"class":188,"line":1359},[186,2208,1630],{"class":420},[186,2210,2211],{"class":479}," user",[186,2213,501],{"class":428},[186,2215,666],{"class":416},[186,2217,596],{"class":428},[186,2219,518],{"class":479},[186,2221,601],{"class":428},[186,2223,675],{"class":507},[186,2225,678],{"class":437},[186,2227,2228,2230,2233,2235],{"class":188,"line":1364},[186,2229,1777],{"class":428},[186,2231,2232],{"class":686},"INSERT INTO users (tenant_id, email, password_hash) VALUES ($1, $2, $3) RETURNING id, email, created_at",[186,2234,690],{"class":428},[186,2236,693],{"class":428},[186,2238,2239,2241,2243,2245,2247,2249,2251,2253,2255,2258,2260,2263,2265,2268,2270,2273],{"class":188,"line":1369},[186,2240,1789],{"class":437},[186,2242,723],{"class":479},[186,2244,601],{"class":428},[186,2246,818],{"class":479},[186,2248,453],{"class":428},[186,2250,2141],{"class":479},[186,2252,453],{"class":428},[186,2254,666],{"class":416},[186,2256,2257],{"class":479}," bcrypt",[186,2259,601],{"class":428},[186,2261,2262],{"class":507},"hash",[186,2264,553],{"class":437},[186,2266,2267],{"class":479},"password",[186,2269,453],{"class":428},[186,2271,2272],{"class":739}," 12",[186,2274,2275],{"class":437},")]\n",[186,2277,2279,2281],{"class":188,"line":2278},63,[186,2280,1824],{"class":437},[186,2282,474],{"class":428},[186,2284,2286],{"class":188,"line":2285},64,[186,2287,1746],{"class":437},[186,2289,2291],{"class":188,"line":2290},65,[186,2292,2293],{"class":410},"      \u002F\u002F Invalidate cache\n",[186,2295,2297,2299,2301,2303,2305,2308,2310,2313,2315,2317,2319,2321,2323,2325,2328,2330,2332],{"class":188,"line":2296},66,[186,2298,1958],{"class":416},[186,2300,596],{"class":428},[186,2302,498],{"class":479},[186,2304,601],{"class":428},[186,2306,2307],{"class":507},"deletePattern",[186,2309,553],{"class":437},[186,2311,2312],{"class":428},"`",[186,2314,1641],{"class":686},[186,2316,1644],{"class":428},[186,2318,723],{"class":479},[186,2320,601],{"class":428},[186,2322,818],{"class":479},[186,2324,1653],{"class":428},[186,2326,2327],{"class":686},":*",[186,2329,2312],{"class":428},[186,2331,611],{"class":437},[186,2333,474],{"class":428},[186,2335,2337],{"class":188,"line":2336},67,[186,2338,1746],{"class":437},[186,2340,2342,2344,2346,2348,2350,2353,2355,2357,2359,2361,2364,2366,2368,2370,2372,2375],{"class":188,"line":2341},68,[186,2343,1992],{"class":479},[186,2345,601],{"class":428},[186,2347,1314],{"class":507},[186,2349,553],{"class":437},[186,2351,2352],{"class":739},"201",[186,2354,611],{"class":437},[186,2356,601],{"class":428},[186,2358,1326],{"class":507},[186,2360,553],{"class":437},[186,2362,2363],{"class":479},"user",[186,2365,601],{"class":428},[186,2367,728],{"class":479},[186,2369,807],{"class":437},[186,2371,810],{"class":739},[186,2373,2374],{"class":437},"])",[186,2376,474],{"class":428},[186,2378,2380],{"class":188,"line":2379},69,[186,2381,1746],{"class":437},[186,2383,2385,2387,2389,2391,2393,2395],{"class":188,"line":2384},70,[186,2386,2014],{"class":428},[186,2388,1294],{"class":416},[186,2390,621],{"class":437},[186,2392,1299],{"class":479},[186,2394,627],{"class":437},[186,2396,630],{"class":428},[186,2398,2400,2402,2404,2406,2408,2411,2413,2415,2417,2419,2421,2423,2425,2427,2429,2432,2434,2436],{"class":188,"line":2399},71,[186,2401,1992],{"class":479},[186,2403,601],{"class":428},[186,2405,1314],{"class":507},[186,2407,553],{"class":437},[186,2409,2410],{"class":739},"400",[186,2412,611],{"class":437},[186,2414,601],{"class":428},[186,2416,1326],{"class":507},[186,2418,553],{"class":437},[186,2420,1331],{"class":428},[186,2422,1334],{"class":437},[186,2424,441],{"class":428},[186,2426,1334],{"class":479},[186,2428,601],{"class":428},[186,2430,2431],{"class":479},"message",[186,2433,1346],{"class":428},[186,2435,611],{"class":437},[186,2437,474],{"class":428},[186,2439,2441],{"class":188,"line":2440},72,[186,2442,644],{"class":428},[186,2444,2446],{"class":188,"line":2445},73,[186,2447,533],{"class":428},[186,2449,2451],{"class":188,"line":2450},74,[186,2452,1372],{"class":428},[24,2454,2455],{},[30,2456,361],{},[34,2458,2459,2465,2471,2476],{},[37,2460,2461,2464],{},[30,2462,2463],{},"Tenant Isolation",": Automatic tenant-specific data filtering",[37,2466,2467,2470],{},[30,2468,2469],{},"Caching",": Performance optimization with cache invalidation",[37,2472,2473,2475],{},[30,2474,1395],{},": Proper error responses and status codes",[37,2477,2478,2481],{},[30,2479,2480],{},"Pagination",": Efficient handling of large datasets",[24,2483,2484,2486],{},[30,2485,390],{}," API response time improved by 80%, concurrent user capacity increased by 500%",[120,2488,2490],{"id":2489},"_2-microservices-architecture","2. Microservices Architecture",[24,2492,2493],{},"We implemented microservices for scalable SaaS:",[176,2495,2497],{"className":401,"code":2496,"language":403,"meta":181,"style":181},"\u002F\u002F User service\nexport class UserService {\n  private db: Database;\n  private eventBus: EventBus;\n  \n  constructor() {\n    this.db = new Database();\n    this.eventBus = new EventBus();\n  }\n  \n  async createUser(tenantId: string, userData: UserData): Promise\u003CUser> {\n    const user = await this.db.query(\n      'INSERT INTO users (tenant_id, email, name) VALUES ($1, $2, $3) RETURNING *',\n      [tenantId, userData.email, userData.name]\n    );\n    \n    \u002F\u002F Publish event for other services\n    await this.eventBus.publish('user.created', {\n      tenantId,\n      userId: user.rows[0].id,\n      userData: user.rows[0]\n    });\n    \n    return user.rows[0];\n  }\n}\n\n\u002F\u002F Notification service\nexport class NotificationService {\n  private eventBus: EventBus;\n  private emailService: EmailService;\n  \n  constructor() {\n    this.eventBus = new EventBus();\n    this.emailService = new EmailService();\n  }\n  \n  async handleUserCreated(event: UserCreatedEvent): Promise\u003Cvoid> {\n    \u002F\u002F Send welcome email\n    await this.emailService.send({\n      to: event.userData.email,\n      template: 'welcome',\n      data: { name: event.userData.name }\n    });\n    \n    \u002F\u002F Send admin notification\n    await this.emailService.send({\n      to: 'admin@company.com',\n      template: 'new-user',\n      data: { \n        tenantId: event.tenantId,\n        userEmail: event.userData.email\n      }\n    });\n  }\n}\n",[183,2498,2499,2504,2515,2527,2541,2545,2553,2569,2586,2590,2594,2632,2652,2663,2688,2694,2698,2703,2730,2737,2762,2781,2789,2793,2811,2815,2819,2823,2828,2839,2851,2865,2869,2877,2893,2910,2914,2918,2947,2952,2969,2990,3006,3033,3041,3045,3050,3066,3081,3096,3107,3122,3140,3144,3152,3156],{"__ignoreMap":181},[186,2500,2501],{"class":188,"line":189},[186,2502,2503],{"class":410},"\u002F\u002F User service\n",[186,2505,2506,2508,2510,2513],{"class":188,"line":195},[186,2507,417],{"class":416},[186,2509,421],{"class":420},[186,2511,2512],{"class":424}," UserService",[186,2514,429],{"class":428},[186,2516,2517,2519,2521,2523,2525],{"class":188,"line":201},[186,2518,434],{"class":420},[186,2520,466],{"class":437},[186,2522,441],{"class":428},[186,2524,471],{"class":424},[186,2526,474],{"class":428},[186,2528,2529,2531,2534,2536,2539],{"class":188,"line":207},[186,2530,434],{"class":420},[186,2532,2533],{"class":437}," eventBus",[186,2535,441],{"class":428},[186,2537,2538],{"class":424}," EventBus",[186,2540,474],{"class":428},[186,2542,2543],{"class":188,"line":213},[186,2544,480],{"class":479},[186,2546,2547,2549,2551],{"class":188,"line":219},[186,2548,485],{"class":420},[186,2550,488],{"class":428},[186,2552,429],{"class":428},[186,2554,2555,2557,2559,2561,2563,2565,2567],{"class":188,"line":225},[186,2556,495],{"class":428},[186,2558,518],{"class":479},[186,2560,501],{"class":428},[186,2562,504],{"class":428},[186,2564,471],{"class":507},[186,2566,488],{"class":437},[186,2568,474],{"class":428},[186,2570,2571,2573,2576,2578,2580,2582,2584],{"class":188,"line":231},[186,2572,495],{"class":428},[186,2574,2575],{"class":479},"eventBus",[186,2577,501],{"class":428},[186,2579,504],{"class":428},[186,2581,2538],{"class":507},[186,2583,488],{"class":437},[186,2585,474],{"class":428},[186,2587,2588],{"class":188,"line":237},[186,2589,533],{"class":428},[186,2591,2592],{"class":188,"line":244},[186,2593,480],{"class":479},[186,2595,2596,2598,2600,2602,2605,2607,2609,2611,2614,2616,2619,2621,2623,2625,2628,2630],{"class":188,"line":250},[186,2597,547],{"class":420},[186,2599,2088],{"class":437},[186,2601,553],{"class":428},[186,2603,2604],{"class":556},"tenantId",[186,2606,441],{"class":428},[186,2608,562],{"class":424},[186,2610,453],{"class":428},[186,2612,2613],{"class":556}," userData",[186,2615,441],{"class":428},[186,2617,2618],{"class":424}," UserData",[186,2620,565],{"class":428},[186,2622,568],{"class":424},[186,2624,447],{"class":428},[186,2626,2627],{"class":424},"User",[186,2629,576],{"class":428},[186,2631,429],{"class":428},[186,2633,2634,2636,2638,2640,2642,2644,2646,2648,2650],{"class":188,"line":255},[186,2635,588],{"class":420},[186,2637,2211],{"class":479},[186,2639,501],{"class":428},[186,2641,666],{"class":416},[186,2643,596],{"class":428},[186,2645,518],{"class":479},[186,2647,601],{"class":428},[186,2649,675],{"class":507},[186,2651,678],{"class":437},[186,2653,2654,2656,2659,2661],{"class":188,"line":261},[186,2655,683],{"class":428},[186,2657,2658],{"class":686},"INSERT INTO users (tenant_id, email, name) VALUES ($1, $2, $3) RETURNING *",[186,2660,690],{"class":428},[186,2662,693],{"class":428},[186,2664,2665,2667,2669,2671,2673,2675,2678,2680,2682,2684,2686],{"class":188,"line":267},[186,2666,698],{"class":437},[186,2668,2604],{"class":479},[186,2670,453],{"class":428},[186,2672,2613],{"class":479},[186,2674,601],{"class":428},[186,2676,2677],{"class":479},"email",[186,2679,453],{"class":428},[186,2681,2613],{"class":479},[186,2683,601],{"class":428},[186,2685,845],{"class":479},[186,2687,703],{"class":437},[186,2689,2690,2692],{"class":188,"line":273},[186,2691,708],{"class":437},[186,2693,474],{"class":428},[186,2695,2696],{"class":188,"line":279},[186,2697,649],{"class":437},[186,2699,2700],{"class":188,"line":284},[186,2701,2702],{"class":410},"    \u002F\u002F Publish event for other services\n",[186,2704,2705,2708,2710,2712,2714,2717,2719,2721,2724,2726,2728],{"class":188,"line":289},[186,2706,2707],{"class":416},"    await",[186,2709,596],{"class":428},[186,2711,2575],{"class":479},[186,2713,601],{"class":428},[186,2715,2716],{"class":507},"publish",[186,2718,553],{"class":437},[186,2720,690],{"class":428},[186,2722,2723],{"class":686},"user.created",[186,2725,690],{"class":428},[186,2727,453],{"class":428},[186,2729,429],{"class":428},[186,2731,2732,2735],{"class":188,"line":295},[186,2733,2734],{"class":479},"      tenantId",[186,2736,693],{"class":428},[186,2738,2739,2742,2744,2746,2748,2750,2752,2754,2756,2758,2760],{"class":188,"line":301},[186,2740,2741],{"class":437},"      userId",[186,2743,441],{"class":428},[186,2745,2211],{"class":479},[186,2747,601],{"class":428},[186,2749,728],{"class":479},[186,2751,807],{"class":437},[186,2753,810],{"class":739},[186,2755,813],{"class":437},[186,2757,601],{"class":428},[186,2759,818],{"class":479},[186,2761,693],{"class":428},[186,2763,2764,2767,2769,2771,2773,2775,2777,2779],{"class":188,"line":307},[186,2765,2766],{"class":437},"      userData",[186,2768,441],{"class":428},[186,2770,2211],{"class":479},[186,2772,601],{"class":428},[186,2774,728],{"class":479},[186,2776,807],{"class":437},[186,2778,810],{"class":739},[186,2780,703],{"class":437},[186,2782,2783,2785,2787],{"class":188,"line":312},[186,2784,2014],{"class":428},[186,2786,611],{"class":437},[186,2788,474],{"class":428},[186,2790,2791],{"class":188,"line":318},[186,2792,649],{"class":437},[186,2794,2795,2797,2799,2801,2803,2805,2807,2809],{"class":188,"line":324},[186,2796,998],{"class":416},[186,2798,2211],{"class":479},[186,2800,601],{"class":428},[186,2802,728],{"class":479},[186,2804,807],{"class":437},[186,2806,810],{"class":739},[186,2808,813],{"class":437},[186,2810,474],{"class":428},[186,2812,2813],{"class":188,"line":330},[186,2814,533],{"class":428},[186,2816,2817],{"class":188,"line":336},[186,2818,1372],{"class":428},[186,2820,2821],{"class":188,"line":341},[186,2822,241],{"emptyLinePlaceholder":240},[186,2824,2825],{"class":188,"line":347},[186,2826,2827],{"class":410},"\u002F\u002F Notification service\n",[186,2829,2830,2832,2834,2837],{"class":188,"line":353},[186,2831,417],{"class":416},[186,2833,421],{"class":420},[186,2835,2836],{"class":424}," NotificationService",[186,2838,429],{"class":428},[186,2840,2841,2843,2845,2847,2849],{"class":188,"line":793},[186,2842,434],{"class":420},[186,2844,2533],{"class":437},[186,2846,441],{"class":428},[186,2848,2538],{"class":424},[186,2850,474],{"class":428},[186,2852,2853,2855,2858,2860,2863],{"class":188,"line":823},[186,2854,434],{"class":420},[186,2856,2857],{"class":437}," emailService",[186,2859,441],{"class":428},[186,2861,2862],{"class":424}," EmailService",[186,2864,474],{"class":428},[186,2866,2867],{"class":188,"line":850},[186,2868,480],{"class":479},[186,2870,2871,2873,2875],{"class":188,"line":876},[186,2872,485],{"class":420},[186,2874,488],{"class":428},[186,2876,429],{"class":428},[186,2878,2879,2881,2883,2885,2887,2889,2891],{"class":188,"line":901},[186,2880,495],{"class":428},[186,2882,2575],{"class":479},[186,2884,501],{"class":428},[186,2886,504],{"class":428},[186,2888,2538],{"class":507},[186,2890,488],{"class":437},[186,2892,474],{"class":428},[186,2894,2895,2897,2900,2902,2904,2906,2908],{"class":188,"line":907},[186,2896,495],{"class":428},[186,2898,2899],{"class":479},"emailService",[186,2901,501],{"class":428},[186,2903,504],{"class":428},[186,2905,2862],{"class":507},[186,2907,488],{"class":437},[186,2909,474],{"class":428},[186,2911,2912],{"class":188,"line":912},[186,2913,533],{"class":428},[186,2915,2916],{"class":188,"line":918},[186,2917,480],{"class":479},[186,2919,2920,2922,2925,2927,2930,2932,2935,2937,2939,2941,2943,2945],{"class":188,"line":942},[186,2921,547],{"class":420},[186,2923,2924],{"class":437}," handleUserCreated",[186,2926,553],{"class":428},[186,2928,2929],{"class":556},"event",[186,2931,441],{"class":428},[186,2933,2934],{"class":424}," UserCreatedEvent",[186,2936,565],{"class":428},[186,2938,568],{"class":424},[186,2940,447],{"class":428},[186,2942,1552],{"class":424},[186,2944,576],{"class":428},[186,2946,429],{"class":428},[186,2948,2949],{"class":188,"line":990},[186,2950,2951],{"class":410},"    \u002F\u002F Send welcome email\n",[186,2953,2954,2956,2958,2960,2962,2965,2967],{"class":188,"line":995},[186,2955,2707],{"class":416},[186,2957,596],{"class":428},[186,2959,2899],{"class":479},[186,2961,601],{"class":428},[186,2963,2964],{"class":507},"send",[186,2966,553],{"class":437},[186,2968,630],{"class":428},[186,2970,2971,2974,2976,2979,2981,2984,2986,2988],{"class":188,"line":1005},[186,2972,2973],{"class":437},"      to",[186,2975,441],{"class":428},[186,2977,2978],{"class":479}," event",[186,2980,601],{"class":428},[186,2982,2983],{"class":479},"userData",[186,2985,601],{"class":428},[186,2987,2677],{"class":479},[186,2989,693],{"class":428},[186,2991,2992,2995,2997,2999,3002,3004],{"class":188,"line":1010},[186,2993,2994],{"class":437},"      template",[186,2996,441],{"class":428},[186,2998,1339],{"class":428},[186,3000,3001],{"class":686},"welcome",[186,3003,690],{"class":428},[186,3005,693],{"class":428},[186,3007,3008,3011,3013,3015,3018,3020,3022,3024,3026,3028,3030],{"class":188,"line":1015},[186,3009,3010],{"class":437},"      data",[186,3012,441],{"class":428},[186,3014,1563],{"class":428},[186,3016,3017],{"class":437}," name",[186,3019,441],{"class":428},[186,3021,2978],{"class":479},[186,3023,601],{"class":428},[186,3025,2983],{"class":479},[186,3027,601],{"class":428},[186,3029,845],{"class":479},[186,3031,3032],{"class":428}," }\n",[186,3034,3035,3037,3039],{"class":188,"line":1021},[186,3036,2014],{"class":428},[186,3038,611],{"class":437},[186,3040,474],{"class":428},[186,3042,3043],{"class":188,"line":1050},[186,3044,649],{"class":437},[186,3046,3047],{"class":188,"line":1091},[186,3048,3049],{"class":410},"    \u002F\u002F Send admin notification\n",[186,3051,3052,3054,3056,3058,3060,3062,3064],{"class":188,"line":1114},[186,3053,2707],{"class":416},[186,3055,596],{"class":428},[186,3057,2899],{"class":479},[186,3059,601],{"class":428},[186,3061,2964],{"class":507},[186,3063,553],{"class":437},[186,3065,630],{"class":428},[186,3067,3068,3070,3072,3074,3077,3079],{"class":188,"line":1119},[186,3069,2973],{"class":437},[186,3071,441],{"class":428},[186,3073,1339],{"class":428},[186,3075,3076],{"class":686},"admin@company.com",[186,3078,690],{"class":428},[186,3080,693],{"class":428},[186,3082,3083,3085,3087,3089,3092,3094],{"class":188,"line":1124},[186,3084,2994],{"class":437},[186,3086,441],{"class":428},[186,3088,1339],{"class":428},[186,3090,3091],{"class":686},"new-user",[186,3093,690],{"class":428},[186,3095,693],{"class":428},[186,3097,3098,3100,3102,3104],{"class":188,"line":1130},[186,3099,3010],{"class":437},[186,3101,441],{"class":428},[186,3103,1563],{"class":428},[186,3105,3106],{"class":437}," \n",[186,3108,3109,3112,3114,3116,3118,3120],{"class":188,"line":1140},[186,3110,3111],{"class":437},"        tenantId",[186,3113,441],{"class":428},[186,3115,2978],{"class":479},[186,3117,601],{"class":428},[186,3119,2604],{"class":479},[186,3121,693],{"class":428},[186,3123,3124,3127,3129,3131,3133,3135,3137],{"class":188,"line":1184},[186,3125,3126],{"class":437},"        userEmail",[186,3128,441],{"class":428},[186,3130,2978],{"class":479},[186,3132,601],{"class":428},[186,3134,2983],{"class":479},[186,3136,601],{"class":428},[186,3138,3139],{"class":479},"email\n",[186,3141,3142],{"class":188,"line":1192},[186,3143,1356],{"class":428},[186,3145,3146,3148,3150],{"class":188,"line":1239},[186,3147,2014],{"class":428},[186,3149,611],{"class":437},[186,3151,474],{"class":428},[186,3153,3154],{"class":188,"line":1262},[186,3155,533],{"class":428},[186,3157,3158],{"class":188,"line":1278},[186,3159,1372],{"class":428},[24,3161,3162],{},[30,3163,361],{},[34,3165,3166,3172,3178,3183],{},[37,3167,3168,3171],{},[30,3169,3170],{},"Service Separation",": Independent, scalable services",[37,3173,3174,3177],{},[30,3175,3176],{},"Event-Driven",": Loose coupling between services",[37,3179,3180,3182],{},[30,3181,53],{},": Each service can scale independently",[37,3184,3185,3188],{},[30,3186,3187],{},"Maintainability",": Easier to maintain and update individual services",[24,3190,3191,3193],{},[30,3192,390],{}," Service scalability improved by 300%, deployment time reduced by 70%",[19,3195,3197],{"id":3196},"performance-optimization-strategies","Performance Optimization Strategies",[120,3199,3201],{"id":3200},"_1-database-optimization","1. Database Optimization",[24,3203,3204],{},"We optimized database performance for multi-tenant SaaS:",[176,3206,3208],{"className":178,"code":3207,"language":180,"meta":181,"style":181},"-- Optimized multi-tenant queries\n-- Use tenant_id in all WHERE clauses for proper isolation\nSELECT u.*, t.name as tenant_name\nFROM users u\nJOIN tenants t ON u.tenant_id = t.id\nWHERE u.tenant_id = $1 AND u.created_at > $2\nORDER BY u.created_at DESC\nLIMIT $3;\n\n-- Optimized indexes for multi-tenant queries\nCREATE INDEX CONCURRENTLY idx_users_tenant_created ON users (tenant_id, created_at);\nCREATE INDEX CONCURRENTLY idx_users_tenant_email ON users (tenant_id, email);\nCREATE INDEX CONCURRENTLY idx_orders_tenant_status ON orders (tenant_id, status);\n\n-- Partitioning for large tables\nCREATE TABLE orders (\n    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    tenant_id UUID NOT NULL,\n    status VARCHAR(50) NOT NULL,\n    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()\n) PARTITION BY RANGE (created_at);\n\n-- Create monthly partitions\nCREATE TABLE orders_2024_01 PARTITION OF orders\nFOR VALUES FROM ('2024-01-01') TO ('2024-02-01');\n",[183,3209,3210,3215,3220,3225,3230,3235,3240,3245,3250,3254,3258,3262,3266,3271,3275,3280,3285,3289,3294,3299,3303,3308,3312,3317,3322],{"__ignoreMap":181},[186,3211,3212],{"class":188,"line":189},[186,3213,3214],{},"-- Optimized multi-tenant queries\n",[186,3216,3217],{"class":188,"line":195},[186,3218,3219],{},"-- Use tenant_id in all WHERE clauses for proper isolation\n",[186,3221,3222],{"class":188,"line":201},[186,3223,3224],{},"SELECT u.*, t.name as tenant_name\n",[186,3226,3227],{"class":188,"line":207},[186,3228,3229],{},"FROM users u\n",[186,3231,3232],{"class":188,"line":213},[186,3233,3234],{},"JOIN tenants t ON u.tenant_id = t.id\n",[186,3236,3237],{"class":188,"line":219},[186,3238,3239],{},"WHERE u.tenant_id = $1 AND u.created_at > $2\n",[186,3241,3242],{"class":188,"line":225},[186,3243,3244],{},"ORDER BY u.created_at DESC\n",[186,3246,3247],{"class":188,"line":231},[186,3248,3249],{},"LIMIT $3;\n",[186,3251,3252],{"class":188,"line":237},[186,3253,241],{"emptyLinePlaceholder":240},[186,3255,3256],{"class":188,"line":244},[186,3257,292],{},[186,3259,3260],{"class":188,"line":250},[186,3261,304],{},[186,3263,3264],{"class":188,"line":255},[186,3265,298],{},[186,3267,3268],{"class":188,"line":261},[186,3269,3270],{},"CREATE INDEX CONCURRENTLY idx_orders_tenant_status ON orders (tenant_id, status);\n",[186,3272,3273],{"class":188,"line":267},[186,3274,241],{"emptyLinePlaceholder":240},[186,3276,3277],{"class":188,"line":273},[186,3278,3279],{},"-- Partitioning for large tables\n",[186,3281,3282],{"class":188,"line":279},[186,3283,3284],{},"CREATE TABLE orders (\n",[186,3286,3287],{"class":188,"line":284},[186,3288,210],{},[186,3290,3291],{"class":188,"line":289},[186,3292,3293],{},"    tenant_id UUID NOT NULL,\n",[186,3295,3296],{"class":188,"line":295},[186,3297,3298],{},"    status VARCHAR(50) NOT NULL,\n",[186,3300,3301],{"class":188,"line":301},[186,3302,228],{},[186,3304,3305],{"class":188,"line":307},[186,3306,3307],{},") PARTITION BY RANGE (created_at);\n",[186,3309,3310],{"class":188,"line":312},[186,3311,241],{"emptyLinePlaceholder":240},[186,3313,3314],{"class":188,"line":318},[186,3315,3316],{},"-- Create monthly partitions\n",[186,3318,3319],{"class":188,"line":324},[186,3320,3321],{},"CREATE TABLE orders_2024_01 PARTITION OF orders\n",[186,3323,3324],{"class":188,"line":330},[186,3325,3326],{},"FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');\n",[24,3328,3329,3332,3333,601],{},[30,3330,3331],{},"Cross-Link to Database Performance:","\nFor detailed database optimization techniques, see our ",[3334,3335,3337],"a",{"href":3336},"\u002Fblog\u002Fpostgresql-performance-strategy","PostgreSQL Performance Tuning Guide",[120,3339,3341],{"id":3340},"_2-caching-strategy","2. Caching Strategy",[24,3343,3344],{},"We implemented comprehensive caching for SaaS applications:",[176,3346,3348],{"className":401,"code":3347,"language":403,"meta":181,"style":181},"\u002F\u002F Multi-layer caching strategy\nexport class SaasCache {\n  private redis: Redis;\n  private memoryCache: Map\u003Cstring, any>;\n  \n  constructor() {\n    this.redis = new Redis(process.env.REDIS_URL);\n    this.memoryCache = new Map();\n  }\n  \n  \u002F\u002F Cache tenant-specific data\n  async cacheTenantData(tenantId: string, key: string, data: any, ttl: number = 300): Promise\u003Cvoid> {\n    const cacheKey = `tenant:${tenantId}:${key}`;\n    \n    \u002F\u002F Memory cache for immediate access\n    this.memoryCache.set(cacheKey, data);\n    \n    \u002F\u002F Redis cache for persistence\n    await this.redis.setex(cacheKey, ttl, JSON.stringify(data));\n  }\n  \n  \u002F\u002F Get cached tenant data\n  async getTenantData(tenantId: string, key: string): Promise\u003Cany> {\n    const cacheKey = `tenant:${tenantId}:${key}`;\n    \n    \u002F\u002F Check memory cache first\n    const memoryCached = this.memoryCache.get(cacheKey);\n    if (memoryCached) {\n      return memoryCached;\n    }\n    \n    \u002F\u002F Check Redis cache\n    const redisCached = await this.redis.get(cacheKey);\n    if (redisCached) {\n      const data = JSON.parse(redisCached);\n      this.memoryCache.set(cacheKey, data);\n      return data;\n    }\n    \n    return null;\n  }\n  \n  \u002F\u002F Invalidate tenant cache\n  async invalidateTenantCache(tenantId: string, pattern: string = '*'): Promise\u003Cvoid> {\n    const keys = await this.redis.keys(`tenant:${tenantId}:${pattern}`);\n    if (keys.length > 0) {\n      await this.redis.del(...keys);\n    }\n    \n    \u002F\u002F Clear memory cache\n    for (const key of this.memoryCache.keys()) {\n      if (key.startsWith(`tenant:${tenantId}:`)) {\n        this.memoryCache.delete(key);\n      }\n    }\n  }\n}\n",[183,3349,3350,3355,3366,3380,3402,3406,3414,3445,3462,3466,3470,3475,3534,3564,3568,3573,3595,3599,3604,3645,3649,3653,3658,3694,3722,3726,3731,3756,3769,3777,3781,3785,3790,3817,3830,3853,3876,3884,3888,3892,3899,3903,3907,3912,3956,4001,4022,4046,4050,4054,4059,4087,4121,4140,4144,4148,4152],{"__ignoreMap":181},[186,3351,3352],{"class":188,"line":189},[186,3353,3354],{"class":410},"\u002F\u002F Multi-layer caching strategy\n",[186,3356,3357,3359,3361,3364],{"class":188,"line":195},[186,3358,417],{"class":416},[186,3360,421],{"class":420},[186,3362,3363],{"class":424}," SaasCache",[186,3365,429],{"class":428},[186,3367,3368,3370,3373,3375,3378],{"class":188,"line":201},[186,3369,434],{"class":420},[186,3371,3372],{"class":437}," redis",[186,3374,441],{"class":428},[186,3376,3377],{"class":424}," Redis",[186,3379,474],{"class":428},[186,3381,3382,3384,3387,3389,3391,3393,3395,3397,3400],{"class":188,"line":207},[186,3383,434],{"class":420},[186,3385,3386],{"class":437}," memoryCache",[186,3388,441],{"class":428},[186,3390,444],{"class":424},[186,3392,447],{"class":428},[186,3394,450],{"class":424},[186,3396,453],{"class":428},[186,3398,3399],{"class":424}," any",[186,3401,459],{"class":428},[186,3403,3404],{"class":188,"line":213},[186,3405,480],{"class":479},[186,3407,3408,3410,3412],{"class":188,"line":219},[186,3409,485],{"class":420},[186,3411,488],{"class":428},[186,3413,429],{"class":428},[186,3415,3416,3418,3421,3423,3425,3427,3429,3432,3434,3436,3438,3441,3443],{"class":188,"line":225},[186,3417,495],{"class":428},[186,3419,3420],{"class":479},"redis",[186,3422,501],{"class":428},[186,3424,504],{"class":428},[186,3426,3377],{"class":507},[186,3428,553],{"class":437},[186,3430,3431],{"class":479},"process",[186,3433,601],{"class":428},[186,3435,1079],{"class":479},[186,3437,601],{"class":428},[186,3439,3440],{"class":479},"REDIS_URL",[186,3442,611],{"class":437},[186,3444,474],{"class":428},[186,3446,3447,3449,3452,3454,3456,3458,3460],{"class":188,"line":231},[186,3448,495],{"class":428},[186,3450,3451],{"class":479},"memoryCache",[186,3453,501],{"class":428},[186,3455,504],{"class":428},[186,3457,444],{"class":507},[186,3459,488],{"class":437},[186,3461,474],{"class":428},[186,3463,3464],{"class":188,"line":237},[186,3465,533],{"class":428},[186,3467,3468],{"class":188,"line":244},[186,3469,480],{"class":479},[186,3471,3472],{"class":188,"line":250},[186,3473,3474],{"class":410},"  \u002F\u002F Cache tenant-specific data\n",[186,3476,3477,3479,3482,3484,3486,3488,3490,3492,3495,3497,3499,3501,3504,3506,3508,3510,3513,3515,3518,3520,3522,3524,3526,3528,3530,3532],{"class":188,"line":255},[186,3478,547],{"class":420},[186,3480,3481],{"class":437}," cacheTenantData",[186,3483,553],{"class":428},[186,3485,2604],{"class":556},[186,3487,441],{"class":428},[186,3489,562],{"class":424},[186,3491,453],{"class":428},[186,3493,3494],{"class":556}," key",[186,3496,441],{"class":428},[186,3498,562],{"class":424},[186,3500,453],{"class":428},[186,3502,3503],{"class":556}," data",[186,3505,441],{"class":428},[186,3507,3399],{"class":424},[186,3509,453],{"class":428},[186,3511,3512],{"class":556}," ttl",[186,3514,441],{"class":428},[186,3516,3517],{"class":424}," number",[186,3519,501],{"class":428},[186,3521,1979],{"class":739},[186,3523,565],{"class":428},[186,3525,568],{"class":424},[186,3527,447],{"class":428},[186,3529,1552],{"class":424},[186,3531,576],{"class":428},[186,3533,429],{"class":428},[186,3535,3536,3538,3540,3542,3544,3547,3549,3551,3553,3555,3557,3560,3562],{"class":188,"line":261},[186,3537,588],{"class":420},[186,3539,1633],{"class":479},[186,3541,501],{"class":428},[186,3543,1638],{"class":428},[186,3545,3546],{"class":686},"tenant:",[186,3548,1644],{"class":428},[186,3550,2604],{"class":479},[186,3552,1653],{"class":428},[186,3554,441],{"class":686},[186,3556,1644],{"class":428},[186,3558,3559],{"class":479},"key",[186,3561,1672],{"class":428},[186,3563,474],{"class":428},[186,3565,3566],{"class":188,"line":267},[186,3567,649],{"class":437},[186,3569,3570],{"class":188,"line":273},[186,3571,3572],{"class":410},"    \u002F\u002F Memory cache for immediate access\n",[186,3574,3575,3577,3579,3581,3583,3585,3587,3589,3591,3593],{"class":188,"line":279},[186,3576,495],{"class":428},[186,3578,3451],{"class":479},[186,3580,601],{"class":428},[186,3582,927],{"class":507},[186,3584,553],{"class":437},[186,3586,1697],{"class":479},[186,3588,453],{"class":428},[186,3590,3503],{"class":479},[186,3592,611],{"class":437},[186,3594,474],{"class":428},[186,3596,3597],{"class":188,"line":284},[186,3598,649],{"class":437},[186,3600,3601],{"class":188,"line":289},[186,3602,3603],{"class":410},"    \u002F\u002F Redis cache for persistence\n",[186,3605,3606,3608,3610,3612,3614,3617,3619,3621,3623,3625,3627,3630,3632,3635,3637,3640,3643],{"class":188,"line":295},[186,3607,2707],{"class":416},[186,3609,596],{"class":428},[186,3611,3420],{"class":479},[186,3613,601],{"class":428},[186,3615,3616],{"class":507},"setex",[186,3618,553],{"class":437},[186,3620,1697],{"class":479},[186,3622,453],{"class":428},[186,3624,3512],{"class":479},[186,3626,453],{"class":428},[186,3628,3629],{"class":479}," JSON",[186,3631,601],{"class":428},[186,3633,3634],{"class":507},"stringify",[186,3636,553],{"class":437},[186,3638,3639],{"class":479},"data",[186,3641,3642],{"class":437},"))",[186,3644,474],{"class":428},[186,3646,3647],{"class":188,"line":301},[186,3648,533],{"class":428},[186,3650,3651],{"class":188,"line":307},[186,3652,480],{"class":479},[186,3654,3655],{"class":188,"line":312},[186,3656,3657],{"class":410},"  \u002F\u002F Get cached tenant data\n",[186,3659,3660,3662,3665,3667,3669,3671,3673,3675,3677,3679,3681,3683,3685,3687,3690,3692],{"class":188,"line":318},[186,3661,547],{"class":420},[186,3663,3664],{"class":437}," getTenantData",[186,3666,553],{"class":428},[186,3668,2604],{"class":556},[186,3670,441],{"class":428},[186,3672,562],{"class":424},[186,3674,453],{"class":428},[186,3676,3494],{"class":556},[186,3678,441],{"class":428},[186,3680,562],{"class":424},[186,3682,565],{"class":428},[186,3684,568],{"class":424},[186,3686,447],{"class":428},[186,3688,3689],{"class":424},"any",[186,3691,576],{"class":428},[186,3693,429],{"class":428},[186,3695,3696,3698,3700,3702,3704,3706,3708,3710,3712,3714,3716,3718,3720],{"class":188,"line":324},[186,3697,588],{"class":420},[186,3699,1633],{"class":479},[186,3701,501],{"class":428},[186,3703,1638],{"class":428},[186,3705,3546],{"class":686},[186,3707,1644],{"class":428},[186,3709,2604],{"class":479},[186,3711,1653],{"class":428},[186,3713,441],{"class":686},[186,3715,1644],{"class":428},[186,3717,3559],{"class":479},[186,3719,1672],{"class":428},[186,3721,474],{"class":428},[186,3723,3724],{"class":188,"line":330},[186,3725,649],{"class":437},[186,3727,3728],{"class":188,"line":336},[186,3729,3730],{"class":410},"    \u002F\u002F Check memory cache first\n",[186,3732,3733,3735,3738,3740,3742,3744,3746,3748,3750,3752,3754],{"class":188,"line":341},[186,3734,588],{"class":420},[186,3736,3737],{"class":479}," memoryCached",[186,3739,501],{"class":428},[186,3741,596],{"class":428},[186,3743,3451],{"class":479},[186,3745,601],{"class":428},[186,3747,604],{"class":507},[186,3749,553],{"class":437},[186,3751,1697],{"class":479},[186,3753,611],{"class":437},[186,3755,474],{"class":428},[186,3757,3758,3760,3762,3765,3767],{"class":188,"line":347},[186,3759,618],{"class":416},[186,3761,621],{"class":437},[186,3763,3764],{"class":479},"memoryCached",[186,3766,627],{"class":437},[186,3768,630],{"class":428},[186,3770,3771,3773,3775],{"class":188,"line":353},[186,3772,635],{"class":416},[186,3774,3737],{"class":479},[186,3776,474],{"class":428},[186,3778,3779],{"class":188,"line":793},[186,3780,644],{"class":428},[186,3782,3783],{"class":188,"line":823},[186,3784,649],{"class":437},[186,3786,3787],{"class":188,"line":850},[186,3788,3789],{"class":410},"    \u002F\u002F Check Redis cache\n",[186,3791,3792,3794,3797,3799,3801,3803,3805,3807,3809,3811,3813,3815],{"class":188,"line":876},[186,3793,588],{"class":420},[186,3795,3796],{"class":479}," redisCached",[186,3798,501],{"class":428},[186,3800,666],{"class":416},[186,3802,596],{"class":428},[186,3804,3420],{"class":479},[186,3806,601],{"class":428},[186,3808,604],{"class":507},[186,3810,553],{"class":437},[186,3812,1697],{"class":479},[186,3814,611],{"class":437},[186,3816,474],{"class":428},[186,3818,3819,3821,3823,3826,3828],{"class":188,"line":901},[186,3820,618],{"class":416},[186,3822,621],{"class":437},[186,3824,3825],{"class":479},"redisCached",[186,3827,627],{"class":437},[186,3829,630],{"class":428},[186,3831,3832,3834,3836,3838,3840,3842,3845,3847,3849,3851],{"class":188,"line":907},[186,3833,1630],{"class":420},[186,3835,3503],{"class":479},[186,3837,501],{"class":428},[186,3839,3629],{"class":479},[186,3841,601],{"class":428},[186,3843,3844],{"class":507},"parse",[186,3846,553],{"class":437},[186,3848,3825],{"class":479},[186,3850,611],{"class":437},[186,3852,474],{"class":428},[186,3854,3855,3858,3860,3862,3864,3866,3868,3870,3872,3874],{"class":188,"line":912},[186,3856,3857],{"class":428},"      this.",[186,3859,3451],{"class":479},[186,3861,601],{"class":428},[186,3863,927],{"class":507},[186,3865,553],{"class":437},[186,3867,1697],{"class":479},[186,3869,453],{"class":428},[186,3871,3503],{"class":479},[186,3873,611],{"class":437},[186,3875,474],{"class":428},[186,3877,3878,3880,3882],{"class":188,"line":918},[186,3879,635],{"class":416},[186,3881,3503],{"class":479},[186,3883,474],{"class":428},[186,3885,3886],{"class":188,"line":942},[186,3887,644],{"class":428},[186,3889,3890],{"class":188,"line":990},[186,3891,649],{"class":437},[186,3893,3894,3896],{"class":188,"line":995},[186,3895,998],{"class":416},[186,3897,3898],{"class":428}," null;\n",[186,3900,3901],{"class":188,"line":1005},[186,3902,533],{"class":428},[186,3904,3905],{"class":188,"line":1010},[186,3906,480],{"class":479},[186,3908,3909],{"class":188,"line":1015},[186,3910,3911],{"class":410},"  \u002F\u002F Invalidate tenant cache\n",[186,3913,3914,3916,3919,3921,3923,3925,3927,3929,3932,3934,3936,3938,3940,3942,3944,3946,3948,3950,3952,3954],{"class":188,"line":1021},[186,3915,547],{"class":420},[186,3917,3918],{"class":437}," invalidateTenantCache",[186,3920,553],{"class":428},[186,3922,2604],{"class":556},[186,3924,441],{"class":428},[186,3926,562],{"class":424},[186,3928,453],{"class":428},[186,3930,3931],{"class":556}," pattern",[186,3933,441],{"class":428},[186,3935,562],{"class":424},[186,3937,501],{"class":428},[186,3939,1339],{"class":428},[186,3941,1815],{"class":686},[186,3943,690],{"class":428},[186,3945,565],{"class":428},[186,3947,568],{"class":424},[186,3949,447],{"class":428},[186,3951,1552],{"class":424},[186,3953,576],{"class":428},[186,3955,429],{"class":428},[186,3957,3958,3960,3963,3965,3967,3969,3971,3973,3976,3978,3980,3982,3984,3986,3988,3990,3992,3995,3997,3999],{"class":188,"line":1050},[186,3959,588],{"class":420},[186,3961,3962],{"class":479}," keys",[186,3964,501],{"class":428},[186,3966,666],{"class":416},[186,3968,596],{"class":428},[186,3970,3420],{"class":479},[186,3972,601],{"class":428},[186,3974,3975],{"class":507},"keys",[186,3977,553],{"class":437},[186,3979,2312],{"class":428},[186,3981,3546],{"class":686},[186,3983,1644],{"class":428},[186,3985,2604],{"class":479},[186,3987,1653],{"class":428},[186,3989,441],{"class":686},[186,3991,1644],{"class":428},[186,3993,3994],{"class":479},"pattern",[186,3996,1672],{"class":428},[186,3998,611],{"class":437},[186,4000,474],{"class":428},[186,4002,4003,4005,4007,4009,4011,4013,4016,4018,4020],{"class":188,"line":1091},[186,4004,618],{"class":416},[186,4006,621],{"class":437},[186,4008,3975],{"class":479},[186,4010,601],{"class":428},[186,4012,733],{"class":479},[186,4014,4015],{"class":428}," >",[186,4017,740],{"class":739},[186,4019,627],{"class":437},[186,4021,630],{"class":428},[186,4023,4024,4026,4028,4030,4032,4035,4037,4040,4042,4044],{"class":188,"line":1114},[186,4025,1958],{"class":416},[186,4027,596],{"class":428},[186,4029,3420],{"class":479},[186,4031,601],{"class":428},[186,4033,4034],{"class":507},"del",[186,4036,553],{"class":437},[186,4038,4039],{"class":428},"...",[186,4041,3975],{"class":479},[186,4043,611],{"class":437},[186,4045,474],{"class":428},[186,4047,4048],{"class":188,"line":1119},[186,4049,644],{"class":428},[186,4051,4052],{"class":188,"line":1124},[186,4053,649],{"class":437},[186,4055,4056],{"class":188,"line":1130},[186,4057,4058],{"class":410},"    \u002F\u002F Clear memory cache\n",[186,4060,4061,4064,4066,4069,4071,4074,4076,4078,4080,4082,4085],{"class":188,"line":1140},[186,4062,4063],{"class":416},"    for",[186,4065,621],{"class":437},[186,4067,4068],{"class":420},"const",[186,4070,3494],{"class":479},[186,4072,4073],{"class":428}," of",[186,4075,596],{"class":428},[186,4077,3451],{"class":479},[186,4079,601],{"class":428},[186,4081,3975],{"class":507},[186,4083,4084],{"class":437},"()) ",[186,4086,630],{"class":428},[186,4088,4089,4091,4093,4095,4097,4100,4102,4104,4106,4108,4110,4112,4114,4116,4119],{"class":188,"line":1184},[186,4090,1706],{"class":416},[186,4092,621],{"class":437},[186,4094,3559],{"class":479},[186,4096,601],{"class":428},[186,4098,4099],{"class":507},"startsWith",[186,4101,553],{"class":437},[186,4103,2312],{"class":428},[186,4105,3546],{"class":686},[186,4107,1644],{"class":428},[186,4109,2604],{"class":479},[186,4111,1653],{"class":428},[186,4113,441],{"class":686},[186,4115,2312],{"class":428},[186,4117,4118],{"class":437},")) ",[186,4120,630],{"class":428},[186,4122,4123,4126,4128,4130,4132,4134,4136,4138],{"class":188,"line":1192},[186,4124,4125],{"class":428},"        this.",[186,4127,3451],{"class":479},[186,4129,601],{"class":428},[186,4131,961],{"class":507},[186,4133,553],{"class":437},[186,4135,3559],{"class":479},[186,4137,611],{"class":437},[186,4139,474],{"class":428},[186,4141,4142],{"class":188,"line":1239},[186,4143,1356],{"class":428},[186,4145,4146],{"class":188,"line":1262},[186,4147,644],{"class":428},[186,4149,4150],{"class":188,"line":1278},[186,4151,533],{"class":428},[186,4153,4154],{"class":188,"line":1288},[186,4155,1372],{"class":428},[24,4157,4158,4161,4162,601],{},[30,4159,4160],{},"Cross-Link to Caching:","\nFor detailed caching strategies, see our ",[3334,4163,4165],{"href":4164},"\u002Fblog\u002Frijmwoordenboek-caching-optimization","Caching Optimization Guide",[19,4167,4169],{"id":4168},"real-world-results","Real-World Results",[120,4171,4173],{"id":4172},"project-case-study-multi-tenant-crm-platform","Project Case Study: Multi-Tenant CRM Platform",[24,4175,4176,4179,4180,4183],{},[30,4177,4178],{},"Client",": B2B CRM platform with 500+ companies\n",[30,4181,4182],{},"Requirements",": Multi-tenant, scalable, high-performance",[24,4185,4186],{},[30,4187,4188],{},"Our Solution:",[34,4190,4191,4197,4202,4208,4213],{},[37,4192,4193,4196],{},[30,4194,4195],{},"Tenant Capacity",": 10,000+ tenants (vs 100 before)",[37,4198,4199,4201],{},[30,4200,78],{},": 50ms average (vs 2-5 seconds before)",[37,4203,4204,4207],{},[30,4205,4206],{},"API Response Time",": 100ms average (vs 1-2 seconds before)",[37,4209,4210,4212],{},[30,4211,96],{},": 99.9% (vs 95% before)",[37,4214,4215,4217],{},[30,4216,90],{},": €800\u002Fmonth (vs €5,000\u002Fmonth before)",[24,4219,4220],{},[30,4221,4222],{},"Technical Implementation:",[176,4224,4226],{"className":401,"code":4225,"language":403,"meta":181,"style":181},"\u002F\u002F Production SaaS architecture\nexport const saasArchitecture = {\n  \u002F\u002F Multi-tenant API endpoint\n  async getTenantData(req: Request, res: Response): Promise\u003Cvoid> {\n    const { tenant } = req;\n    const startTime = Date.now();\n    \n    try {\n      \u002F\u002F Check cache first\n      const cached = await this.cache.getTenantData(tenant.id, 'dashboard');\n      if (cached) {\n        res.json(cached);\n        return;\n      }\n      \n      \u002F\u002F Query database with tenant isolation\n      const data = await this.db.query(\n        'SELECT * FROM dashboard_data WHERE tenant_id = $1',\n        [tenant.id]\n      );\n      \n      \u002F\u002F Cache result\n      await this.cache.cacheTenantData(tenant.id, 'dashboard', data.rows, 300);\n      \n      const duration = Date.now() - startTime;\n      console.log(`Tenant data retrieved in ${duration}ms`);\n      \n      res.json(data.rows);\n      \n    } catch (error) {\n      res.status(500).json({ error: 'Internal server error' });\n    }\n  }\n};\n",[183,4227,4228,4233,4248,4253,4287,4303,4324,4328,4334,4338,4378,4390,4406,4412,4416,4420,4424,4444,4455,4467,4473,4477,4482,4527,4531,4556,4589,4593,4613,4617,4631,4669,4673,4677],{"__ignoreMap":181},[186,4229,4230],{"class":188,"line":189},[186,4231,4232],{"class":410},"\u002F\u002F Production SaaS architecture\n",[186,4234,4235,4237,4240,4243,4246],{"class":188,"line":195},[186,4236,417],{"class":416},[186,4238,4239],{"class":420}," const",[186,4241,4242],{"class":479}," saasArchitecture ",[186,4244,4245],{"class":428},"=",[186,4247,429],{"class":428},[186,4249,4250],{"class":188,"line":201},[186,4251,4252],{"class":410},"  \u002F\u002F Multi-tenant API endpoint\n",[186,4254,4255,4257,4259,4261,4263,4265,4267,4269,4271,4273,4275,4277,4279,4281,4283,4285],{"class":188,"line":207},[186,4256,547],{"class":420},[186,4258,3664],{"class":437},[186,4260,553],{"class":428},[186,4262,1150],{"class":556},[186,4264,441],{"class":428},[186,4266,1155],{"class":424},[186,4268,453],{"class":428},[186,4270,1160],{"class":556},[186,4272,441],{"class":428},[186,4274,1165],{"class":424},[186,4276,565],{"class":428},[186,4278,568],{"class":424},[186,4280,447],{"class":428},[186,4282,1552],{"class":424},[186,4284,576],{"class":428},[186,4286,429],{"class":428},[186,4288,4289,4291,4293,4295,4297,4299,4301],{"class":188,"line":213},[186,4290,588],{"class":420},[186,4292,1563],{"class":428},[186,4294,661],{"class":479},[186,4296,1346],{"class":428},[186,4298,501],{"class":428},[186,4300,1203],{"class":479},[186,4302,474],{"class":428},[186,4304,4305,4307,4310,4312,4315,4317,4320,4322],{"class":188,"line":219},[186,4306,588],{"class":420},[186,4308,4309],{"class":479}," startTime",[186,4311,501],{"class":428},[186,4313,4314],{"class":479}," Date",[186,4316,601],{"class":428},[186,4318,4319],{"class":507},"now",[186,4321,488],{"class":437},[186,4323,474],{"class":428},[186,4325,4326],{"class":188,"line":225},[186,4327,649],{"class":437},[186,4329,4330,4332],{"class":188,"line":231},[186,4331,1618],{"class":416},[186,4333,429],{"class":428},[186,4335,4336],{"class":188,"line":237},[186,4337,1625],{"class":410},[186,4339,4340,4342,4344,4346,4348,4350,4352,4354,4357,4359,4361,4363,4365,4367,4369,4372,4374,4376],{"class":188,"line":244},[186,4341,1630],{"class":420},[186,4343,591],{"class":479},[186,4345,501],{"class":428},[186,4347,666],{"class":416},[186,4349,596],{"class":428},[186,4351,498],{"class":479},[186,4353,601],{"class":428},[186,4355,4356],{"class":507},"getTenantData",[186,4358,553],{"class":437},[186,4360,723],{"class":479},[186,4362,601],{"class":428},[186,4364,818],{"class":479},[186,4366,453],{"class":428},[186,4368,1339],{"class":428},[186,4370,4371],{"class":686},"dashboard",[186,4373,690],{"class":428},[186,4375,611],{"class":437},[186,4377,474],{"class":428},[186,4379,4380,4382,4384,4386,4388],{"class":188,"line":250},[186,4381,1706],{"class":416},[186,4383,621],{"class":437},[186,4385,624],{"class":479},[186,4387,627],{"class":437},[186,4389,630],{"class":428},[186,4391,4392,4394,4396,4398,4400,4402,4404],{"class":188,"line":255},[186,4393,1309],{"class":479},[186,4395,601],{"class":428},[186,4397,1326],{"class":507},[186,4399,553],{"class":437},[186,4401,624],{"class":479},[186,4403,611],{"class":437},[186,4405,474],{"class":428},[186,4407,4408,4410],{"class":188,"line":261},[186,4409,1735],{"class":416},[186,4411,474],{"class":428},[186,4413,4414],{"class":188,"line":267},[186,4415,1356],{"class":428},[186,4417,4418],{"class":188,"line":273},[186,4419,1746],{"class":437},[186,4421,4422],{"class":188,"line":279},[186,4423,1751],{"class":410},[186,4425,4426,4428,4430,4432,4434,4436,4438,4440,4442],{"class":188,"line":284},[186,4427,1630],{"class":420},[186,4429,3503],{"class":479},[186,4431,501],{"class":428},[186,4433,666],{"class":416},[186,4435,596],{"class":428},[186,4437,518],{"class":479},[186,4439,601],{"class":428},[186,4441,675],{"class":507},[186,4443,678],{"class":437},[186,4445,4446,4448,4451,4453],{"class":188,"line":289},[186,4447,1777],{"class":428},[186,4449,4450],{"class":686},"SELECT * FROM dashboard_data WHERE tenant_id = $1",[186,4452,690],{"class":428},[186,4454,693],{"class":428},[186,4456,4457,4459,4461,4463,4465],{"class":188,"line":295},[186,4458,1789],{"class":437},[186,4460,723],{"class":479},[186,4462,601],{"class":428},[186,4464,818],{"class":479},[186,4466,703],{"class":437},[186,4468,4469,4471],{"class":188,"line":301},[186,4470,1824],{"class":437},[186,4472,474],{"class":428},[186,4474,4475],{"class":188,"line":307},[186,4476,1746],{"class":437},[186,4478,4479],{"class":188,"line":312},[186,4480,4481],{"class":410},"      \u002F\u002F Cache result\n",[186,4483,4484,4486,4488,4490,4492,4495,4497,4499,4501,4503,4505,4507,4509,4511,4513,4515,4517,4519,4521,4523,4525],{"class":188,"line":318},[186,4485,1958],{"class":416},[186,4487,596],{"class":428},[186,4489,498],{"class":479},[186,4491,601],{"class":428},[186,4493,4494],{"class":507},"cacheTenantData",[186,4496,553],{"class":437},[186,4498,723],{"class":479},[186,4500,601],{"class":428},[186,4502,818],{"class":479},[186,4504,453],{"class":428},[186,4506,1339],{"class":428},[186,4508,4371],{"class":686},[186,4510,690],{"class":428},[186,4512,453],{"class":428},[186,4514,3503],{"class":479},[186,4516,601],{"class":428},[186,4518,728],{"class":479},[186,4520,453],{"class":428},[186,4522,1979],{"class":739},[186,4524,611],{"class":437},[186,4526,474],{"class":428},[186,4528,4529],{"class":188,"line":324},[186,4530,1746],{"class":437},[186,4532,4533,4535,4538,4540,4542,4544,4546,4549,4552,4554],{"class":188,"line":330},[186,4534,1630],{"class":420},[186,4536,4537],{"class":479}," duration",[186,4539,501],{"class":428},[186,4541,4314],{"class":479},[186,4543,601],{"class":428},[186,4545,4319],{"class":507},[186,4547,4548],{"class":437},"() ",[186,4550,4551],{"class":428},"-",[186,4553,4309],{"class":479},[186,4555,474],{"class":428},[186,4557,4558,4561,4563,4566,4568,4570,4573,4575,4578,4580,4583,4585,4587],{"class":188,"line":336},[186,4559,4560],{"class":479},"      console",[186,4562,601],{"class":428},[186,4564,4565],{"class":507},"log",[186,4567,553],{"class":437},[186,4569,2312],{"class":428},[186,4571,4572],{"class":686},"Tenant data retrieved in ",[186,4574,1644],{"class":428},[186,4576,4577],{"class":479},"duration",[186,4579,1653],{"class":428},[186,4581,4582],{"class":686},"ms",[186,4584,2312],{"class":428},[186,4586,611],{"class":437},[186,4588,474],{"class":428},[186,4590,4591],{"class":188,"line":341},[186,4592,1746],{"class":437},[186,4594,4595,4597,4599,4601,4603,4605,4607,4609,4611],{"class":188,"line":347},[186,4596,1992],{"class":479},[186,4598,601],{"class":428},[186,4600,1326],{"class":507},[186,4602,553],{"class":437},[186,4604,3639],{"class":479},[186,4606,601],{"class":428},[186,4608,728],{"class":479},[186,4610,611],{"class":437},[186,4612,474],{"class":428},[186,4614,4615],{"class":188,"line":353},[186,4616,1746],{"class":437},[186,4618,4619,4621,4623,4625,4627,4629],{"class":188,"line":793},[186,4620,2014],{"class":428},[186,4622,1294],{"class":416},[186,4624,621],{"class":437},[186,4626,1299],{"class":479},[186,4628,627],{"class":437},[186,4630,630],{"class":428},[186,4632,4633,4635,4637,4639,4641,4643,4645,4647,4649,4651,4653,4655,4657,4659,4661,4663,4665,4667],{"class":188,"line":823},[186,4634,1992],{"class":479},[186,4636,601],{"class":428},[186,4638,1314],{"class":507},[186,4640,553],{"class":437},[186,4642,2037],{"class":739},[186,4644,611],{"class":437},[186,4646,601],{"class":428},[186,4648,1326],{"class":507},[186,4650,553],{"class":437},[186,4652,1331],{"class":428},[186,4654,1334],{"class":437},[186,4656,441],{"class":428},[186,4658,1339],{"class":428},[186,4660,2056],{"class":686},[186,4662,690],{"class":428},[186,4664,1346],{"class":428},[186,4666,611],{"class":437},[186,4668,474],{"class":428},[186,4670,4671],{"class":188,"line":850},[186,4672,644],{"class":428},[186,4674,4675],{"class":188,"line":876},[186,4676,533],{"class":428},[186,4678,4679],{"class":188,"line":901},[186,4680,4681],{"class":428},"};\n",[19,4683,4685],{"id":4684},"key-success-factors","Key Success Factors",[120,4687,4689],{"id":4688},"_1-multi-tenant-design","1. Multi-Tenant Design",[34,4691,4692,4696,4701,4705],{},[37,4693,4694,369],{},[30,4695,368],{},[37,4697,4698,4700],{},[30,4699,47],{},": Optimized queries and indexes",[37,4702,4703,379],{},[30,4704,53],{},[37,4706,4707,385],{},[30,4708,384],{},[120,4710,4712],{"id":4711},"_2-api-architecture","2. API Architecture",[34,4714,4715,4721,4725,4729],{},[37,4716,4717,4720],{},[30,4718,4719],{},"RESTful Design",": Consistent, predictable API patterns",[37,4722,4723,2470],{},[30,4724,2469],{},[37,4726,4727,2475],{},[30,4728,1395],{},[37,4730,4731,4734],{},[30,4732,4733],{},"Documentation",": Clear API documentation for developers",[120,4736,4738],{"id":4737},"_3-microservices-architecture","3. Microservices Architecture",[34,4740,4741,4745,4749,4753],{},[37,4742,4743,3171],{},[30,4744,3170],{},[37,4746,4747,3177],{},[30,4748,3176],{},[37,4750,4751,3182],{},[30,4752,53],{},[37,4754,4755,3188],{},[30,4756,3187],{},[120,4758,4760],{"id":4759},"_4-performance-optimization","4. Performance Optimization",[34,4762,4763,4768,4772,4778],{},[37,4764,4765,4700],{},[30,4766,4767],{},"Database Tuning",[37,4769,4770,151],{},[30,4771,150],{},[37,4773,4774,4777],{},[30,4775,4776],{},"Monitoring",": Real-time performance monitoring",[37,4779,4780,4783],{},[30,4781,4782],{},"Scaling",": Horizontal and vertical scaling strategies",[19,4785,4787],{"id":4786},"implementation-checklist","Implementation Checklist",[24,4789,4790],{},"If you're building SaaS applications:",[34,4792,4795,4808,4817,4826,4834,4842,4851,4860],{"className":4793},[4794],"contains-task-list",[37,4796,4799,4803,4804,4807],{"className":4797},[4798],"task-list-item",[4800,4801],"input",{"disabled":240,"type":4802},"checkbox"," ",[30,4805,4806],{},"Design multi-tenant architecture",": Choose appropriate database pattern",[37,4809,4811,4803,4813,4816],{"className":4810},[4798],[4800,4812],{"disabled":240,"type":4802},[30,4814,4815],{},"Implement tenant resolution",": Fast, cached tenant lookup",[37,4818,4820,4803,4822,4825],{"className":4819},[4798],[4800,4821],{"disabled":240,"type":4802},[30,4823,4824],{},"Build scalable APIs",": RESTful design with proper error handling",[37,4827,4829,4803,4831,151],{"className":4828},[4798],[4800,4830],{"disabled":240,"type":4802},[30,4832,4833],{},"Add caching layers",[37,4835,4837,4803,4839,157],{"className":4836},[4798],[4800,4838],{"disabled":240,"type":4802},[30,4840,4841],{},"Implement microservices",[37,4843,4845,4803,4847,4850],{"className":4844},[4798],[4800,4846],{"disabled":240,"type":4802},[30,4848,4849],{},"Optimize database",": Proper indexes and query optimization",[37,4852,4854,4803,4856,4859],{"className":4853},[4798],[4800,4855],{"disabled":240,"type":4802},[30,4857,4858],{},"Monitor performance",": Real-time monitoring and alerting",[37,4861,4863,4803,4865,4783],{"className":4862},[4798],[4800,4864],{"disabled":240,"type":4802},[30,4866,4867],{},"Plan for scale",[19,4869,4871],{"id":4870},"cross-linked-resources","Cross-Linked Resources",[24,4873,4874],{},"SaaS architecture patterns often intersect with other development areas:",[34,4876,4877,4885,4893,4902],{},[37,4878,4879,4884],{},[30,4880,4881],{},[3334,4882,4883],{"href":3336},"PostgreSQL Performance Tuning",": Database optimization for SaaS",[37,4886,4887,4892],{},[30,4888,4889],{},[3334,4890,4891],{"href":4164},"Caching Optimization",": Performance optimization",[37,4894,4895,4901],{},[30,4896,4897],{},[3334,4898,4900],{"href":4899},"\u002Fblog\u002Fauthentication-strategies","Authentication Strategies",": Multi-tenant authentication",[37,4903,4904,4910],{},[30,4905,4906],{},[3334,4907,4909],{"href":4908},"\u002Fblog\u002Fcustomer-portal-development","Customer Portal Development",": Portal architecture patterns",[19,4912,4914],{"id":4913},"summary","Summary",[24,4916,4917],{},"SaaS architecture doesn't have to be complex or expensive. By implementing proven patterns for multi-tenancy, API design, and performance optimization, we've built scalable SaaS applications that handle growth from startup to enterprise scale.",[24,4919,4920],{},"The key is treating SaaS architecture as a system-wide concern that requires careful planning, implementation, and ongoing optimization.",[24,4922,4923],{},"If this article helped you understand SaaS architecture patterns, we can help you build scalable SaaS applications. At Ludulicious, we specialize in:",[34,4925,4926,4932,4937,4943],{},[37,4927,4928,4931],{},[30,4929,4930],{},"SaaS Architecture",": Scalable, multi-tenant application design",[37,4933,4934,4936],{},[30,4935,162],{},": Fast, efficient SaaS applications",[37,4938,4939,4942],{},[30,4940,4941],{},"Database Design",": Multi-tenant database architecture",[37,4944,4945,4948],{},[30,4946,4947],{},"API Development",": RESTful, scalable API design",[24,4950,4951],{},[30,4952,4953],{},"Ready to build scalable SaaS applications?",[24,4955,4956,4960],{},[3334,4957,4959],{"href":4958},"\u002Fcontact","Contact us"," for a free consultation, or check out our other development guides:",[34,4962,4963,4968,4973,4978],{},[37,4964,4965],{},[3334,4966,4967],{"href":3336},"PostgreSQL Performance Tuning: Strategic Lessons from Production",[37,4969,4970],{},[3334,4971,4972],{"href":4908},"Customer Portal Development: From 6 Months to 6 Weeks",[37,4974,4975],{},[3334,4976,4977],{"href":4899},"Authentication Strategies: Secure, Fast User Management",[37,4979,4980],{},[3334,4981,4982],{"href":4164},"Caching Optimization: Sub-15ms Response Times",[4984,4985],"hr",{},[24,4987,4988],{},[4989,4990,4991],"em",{},"This SaaS architecture guide is based on real production experience building scalable SaaS applications. All performance numbers and scalability metrics are from actual production systems.",[4993,4994,4995],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":181,"searchDepth":195,"depth":195,"links":4997},[4998,4999,5002,5006,5010,5014,5017,5023,5024,5025],{"id":21,"depth":195,"text":22},{"id":117,"depth":195,"text":118,"children":5000},[5001],{"id":122,"depth":201,"text":123},{"id":166,"depth":195,"text":167,"children":5003},[5004,5005],{"id":170,"depth":201,"text":171},{"id":394,"depth":201,"text":395},{"id":1409,"depth":195,"text":1410,"children":5007},[5008,5009],{"id":1413,"depth":201,"text":1414},{"id":2489,"depth":201,"text":2490},{"id":3196,"depth":195,"text":3197,"children":5011},[5012,5013],{"id":3200,"depth":201,"text":3201},{"id":3340,"depth":201,"text":3341},{"id":4168,"depth":195,"text":4169,"children":5015},[5016],{"id":4172,"depth":201,"text":4173},{"id":4684,"depth":195,"text":4685,"children":5018},[5019,5020,5021,5022],{"id":4688,"depth":201,"text":4689},{"id":4711,"depth":201,"text":4712},{"id":4737,"depth":201,"text":4738},{"id":4759,"depth":201,"text":4760},{"id":4786,"depth":195,"text":4787},{"id":4870,"depth":195,"text":4871},{"id":4913,"depth":195,"text":4914},[14,5027],"SaaS","2025-01-17","Learn proven SaaS architecture patterns for building scalable, multi-tenant applications. Real-world strategies for database design, API architecture, and deployment that handle growth from startup to enterprise scale.","md",{"src":5032},"https:\u002F\u002Fpicsum.photos\u002Fid\u002F17\u002F640\u002F360",{"schema":5034},{"type":5035,"name":5,"description":5029,"image":5032,"author":5036,"datePublished":5028,"dateModified":5028,"publisher":5037,"steps":5040,"totalTime":5059,"estimatedCost":5060},"HowTo",{"name":8,"url":9},{"name":5038,"url":5039},"Ludulicious B.V.","https:\u002F\u002Fludulicious.nl",[5041,5044,5047,5050,5053,5056],{"name":5042,"text":5043},"Design Multi-Tenant Database","Choose appropriate database pattern for multi-tenancy (shared schema, separate schema, or separate database)",{"name":5045,"text":5046},"Implement Tenant Resolution","Set up fast, cached tenant lookup system",{"name":5048,"text":5049},"Build Scalable APIs","Design RESTful APIs with proper tenant isolation and caching",{"name":5051,"text":5052},"Add Microservices Architecture","Implement modular, scalable service design",{"name":5054,"text":5055},"Configure Performance Optimization","Optimize database queries, implement caching, and configure monitoring",{"name":5057,"text":5058},"Plan for Scale","Design horizontal and vertical scaling strategies","PT4W",{"currency":5061,"value":5062},"EUR","25000","\u002Fblog\u002Fsaas-architecture-patterns",{"title":5,"description":5029},"blog\u002F13.saas-architecture-patterns",[4930,41,53,4941,5067,5068,47],"API Design","Microservices","H62Cn304Bp0G7Ll9qYT76XdCXUJeh8VD8E7UKYaoR0Y",[5071,5074],{"title":4977,"path":4899,"stem":5072,"description":5073,"children":-1},"blog\u002F12.authentication-strategies","Learn modern authentication strategies for web applications, from OAuth2 flows to session management. Real-world implementation patterns that ensure security while maintaining optimal performance and user experience.",{"title":5075,"path":5076,"stem":5077,"description":5078,"children":-1},"TypeScript Best Practices: Type-Safe Development","\u002Fblog\u002Ftypescript-best-practices","blog\u002F14.typescript-best-practices","Learn TypeScript best practices for building type-safe, maintainable applications. Real-world patterns for type definitions, error handling, and performance optimization that prevent runtime errors and improve code quality.",[]]