One self-hosted console to run your entire business — commerce, ERP, HRM, CRM & manufacturing

भाग 1: NovaCommerce के लिए High Availability असली में क्या था

काल्पनिक नाम, लेकिन real संख्या: एक frontend server, दो fixed backend, एक database node और दो powered-off standby। इस भाग में high availability की definition है और bottleneck बार-बार हटता है।

Author

Anichur Rahaman

1 सप्ताह पहले13 min read5 views
भाग 1: NovaCommerce के लिए High Availability असली में क्या था

25 सितंबर को परीक्षा के दौरान विद्यार्थियों को HTTP 429 "बहुत ज़्यादा अनुरोध" दिखने लगे। समस्या सर्वरों की कमी नहीं थी। यह एक नियम था जो ग़लत चीज़ गुन रहा था: एक rate limiter IP address से गिन रहा था, और एक स्कूल सैकड़ों विद्यार्थियों को एक address के पीछे रखता है। limiter को एक पूरी इमारत एक बहुत ही बेसब्र आदमी दिख रहा था।

ग्यारह दिन बाद, 6 अक्टूबर को 02:28 पर, एक backend load test 2,854 application error दे गया। हर एक यही कह रहा था: Valkey से connection timeout हो गया। एक अलग layer, एक अलग कारण, एक अलग हल। उसके बाद सिर्फ़ CPU रहा, जो वह समस्या है जिसे ज़्यादा सर्वर से सच में हल होता है।

यह क्रम इसी project की असली कहानी है: bottleneck बार-बार हटता रहा। सर्वर जोड़ना architecture नहीं है। यह कई काम में से एक है, और आख़िरी।

सितंबर के अंत से 7 अक्टूबर 2026 तक, हमने DigitalOcean पर एक Laravel और Next.js प्लेटफ़ॉर्म को एक frontend सर्वर और दो fixed backend से एक scheduled exam peak के लिए तैयार setup में ले गए। यह पहला हिस्सा starting point को cover करता है: business की समस्या, जो हमें मिला उसे, क्यों यह काफ़ी नहीं था, "high availability" हमारे लिए क्या मतलब था, और पहले test ने हमें क्या सिखाया।

शुरुआत से पहले: NovaCommerce एक काल्पनिक नाम है, इस case study के लिए। मैंने कुछ भी ऐसा नहीं रखा जो कंपनी, उसके सर्वर या विद्यार्थियों को पहचान सके।

यह "From One Server to Exam-Day Ready" five-part case study का हिस्सा 1 है। NovaCommerce एक काल्पनिक नाम है; architecture, संख्याएँ और गलतियाँ वास्तविक हैं।

एक प्लेटफ़ॉर्म जिसका traffic एक शेड्यूल पर आता है

NovaCommerce एक online platform है जो courses बेचता है और विद्यार्थियों के लिए timed online exams चलाता है। लोग sign up करते हैं, pay करते हैं, live exams लेते हैं, अपने results देखते हैं और AI study help इस्तेमाल करते हैं।

ज़्यादातर web traffic एक पहाड़ी है: सुबह बढ़ता है और रात को गिरता है। Exam traffic एक cliff है। concert hall के दरवाज़ों की तरह सोचें। घंटों कुछ नहीं होता, फिर दरवाज़े खुलते हैं और सब एक साथ आते हैं। जब एक scheduled exam शुरू होता है, हज़ारों विद्यार्थी एक ही मिनट में platform पर आते हैं।

अच्छी बात है कि cliff का एक timetable है। हम जानते हैं कि यह कब आएगा। मैं इस फ़ायदे को general terms में traffic spikes के लिए autoscaling के guide में बताता हूँ। यह series दूसरा आधा है: एक असली platform, असली संख्याओं के साथ।

Business ने हमें चार requirements दी, सादी भाषा में।

  1. Exam spikes scheduled और sharp होते हैं। हज़ारों विद्यार्थी एक ही मिनट में आते हैं।
  2. Submissions कभी नहीं खोने चाहिए। एक slow page irritating है। एक lost exam submission एक विद्यार्थी का काम गायब है।
  3. Deploys invisible होने चाहिए। Site को ऊपर रहना चाहिए जबकि हम एक release भेजते हैं।
  4. Cost सही रहना चाहिए। Capacity जिसकी कोई ज़रूरत नहीं एक defect भी है।

इस series में हर technical choice इन चार lines में से किसी एक पर जाता है।

Starting point: जो हमें मिला

यहाँ setup है जैसा हमने 5 अक्टूबर 2026 से पहले पाया, एक DigitalOcean region में और एक private network में।

Original setup का diagram: विद्यार्थी एक frontend droplet तक पहुँचते हैं, फिर एक backend load balancer जो ID से दो fixed backend droplet को target करता है, फिर एक MySQL node, Valkey और एक worker; दो powered-off standby droplet अलग बैठे हैं, अब भी bill किए जा रहे हैं
दो single points of failure (frontend और database), दो fixed backend की एक list, और दो standby server जो बंद हैं लेकिन bill किए जा रहे हैं।

Frontend: एक सर्वर, आठ CPU, एक cashier

Frontend एक single droplet था जिसमें 8 vCPU और 16 GB memory था, एक Next.js container चला रहा था। Domain सीधा इस पर point करता था, और TLS certbot से droplet पर आता था। कोई load balancer नहीं था। अगर यह सर्वर मर जाता, तो site down हो जाता।

यह पैसे भी बर्बाद कर रहा था। एक Node.js process roughly एक core पर render करता है, तो ज़्यादातर आठ vCPU idle बैठे थे: एक दुकान आठ tills के साथ और एक cashier।

Backend: दो सर्वर जिन्हें load balancer grow नहीं कर सकता था

एक DigitalOcean load balancer दो fixed backend droplet के सामने था, हर एक 4 vCPU और 8 GB के साथ। Application Laravel है (PHP-FPM) nginx के पीछे Docker में, दो container per node: nginx के लिए web और php-fpm के लिए app। Queues (Horizon), scheduler और Reverb, WebSocket server live updates के लिए, एक worker पर चलते थे।

Load balancer हर backend को अपने fixed ID से target करता था, tag से नहीं। यह एक guest list जिसमें नाम लिखे हों और एक rule जो "कोई भी staff badge पहने" के बीच का फ़र्क़ है। नामों के साथ, एक नया सर्वर कभी अपने आप अंदर नहीं जा सकता। किसी को list edit करनी पड़ती है।

यहाँ अच्छी बात थी, और यह बाकी सब से ज़्यादा मायने रखती थी। Backend web nodes पहले से ही stateless थे। Sessions, cache और queues managed Valkey में रहते थे, और logs stderr को जाते थे। एक सर्वर जिसे बिना कुछ खोए delete किया जा सके एक सर्वर है जिसे multiply किया जा सकता है। इस property के बिना series का बाकी हिस्सा हो नहीं सकता था।

Database और switched-off standbys

Database एक Managed MySQL "Advanced" node था 8 vCPU और 32 GB के साथ: एक single node, कोई standby नहीं।

फिर दो "standby" droplet थे, एक backup के रूप में रखे गए। वे powered off थे। एक powered-off droplet अब भी पैसे लेता है, और एक को ऊपर लाने में मिनट लगते हैं। यह एक spare टायर एक locked garage के पार शहर में है: यह exist करता है, आप इसके लिए pay करते हैं, और जबकि आप सड़क पर stuck हैं यह मदद नहीं करता। यह high availability नहीं है।

दो छोटी चीज़ें कोने में बैठी थीं। Load balancer के TLS certificates manual uploads थे जिनके expiry date थे, तो renewal एक recurring task था जिसे किसी को याद रखना था। और account की droplet limit 25 थी, जो मायने रखती थी एक बार दो pools grow कर सकते और nodes replace कर सकते (part 2)।

क्यों यह काफ़ी नहीं था

Setup का हिस्साकैसे बनाया गया थाStress या failure के अंतर्गत क्या होता है
Frontendएक 8 vCPU / 16 GB droplet, एक Next.js container, कोई load balancer नहींअगर यह मरता है तो site down; ज़्यादातर cores idle, क्योंकि एक Node process लगभग एक core इस्तेमाल करता है
Backendदो fixed 4 vCPU / 8 GB droplet एक load balancer के पीछे, ID से target किए गएकोई automatic growth नहीं; एक नया सर्वर कभी अपने आप join नहीं कर सकता
Databaseएक Managed MySQL node, 8 vCPU / 32 GB, कोई standby नहींअगर node fail करता है तो कोई दूसरा node लेने के लिए तैयार नहीं
Standbysदो droplet, powered offOff होने पर भी bill किए जा रहे हैं; ऊपर लाने में मिनट लगते हैं

देखें कि उस table में क्या missing है: एक bug। कुछ नहीं टूटा था। Setup वह करता था जिसके लिए यह बनाया गया था। Trouble एक scheduled cliff और एक setup के बीच mismatch था जो एक सर्वर नहीं खो सकता, अपने आप एक नहीं जोड़ सकता, और अपनी spare capacity को switched off रखता है। आप एक mismatch को patch नहीं कर सकते। आपको system की form change करनी पड़ती है, और यही architecture मतलब है।

"High availability" यहाँ सच में क्या मतलब था

"High availability" एक ऐसा phrase है जिसमें सब लोग सिर हिलाते हैं और कोई define नहीं करता। हम कुछ भी change करने से पहले, हमने लिख दिया कि यह इस platform के लिए क्या मतलब है। यह चार lines में आ गया।

कोई भी single server जिसका loss site को down ले जाए। Database एक node के loss से survive करता है। Deploys और scale-in विद्यार्थियों को invisible होते हैं। Capacity एक exam के बाद नहीं, पहले ready है।

मुझे एक definition पसंद है जिसे आप एक सवाल से test कर सकते। क्या हम किसी भी एक सर्वर की plug निकाल सकते और serving चलती रहती है? क्या एक database node fail कर सकता है बिना exam रुके? क्या हम एक release ship कर सकते बिना विद्यार्थी को notice किए? क्या capacity पहले से ही वहाँ है जब पहला विद्यार्थी "start" click करता है?

दो business rules इसके ऊपर बैठते हैं: submissions कभी नहीं खोते, और cost sane रहता है। Figure हर requirement को map करता है इस layer को जो इसे deliver करता है और series के इस part को जो इसे cover करता है।

Five requirements mapped इस layer को जो हर एक को deliver करता है और इस series part को जो इसे cover करता है: load balancer और pools (part 2), managed MySQL एक standby के साथ (part 3), health check और guarded rollout (part 2 और 4), pre-scaling (part 2 और 5), stateless nodes (part 4), plus एक cost rule
हर requirement के एक owner होता है: एक layer जो इसे deliver करता है, और इस series का एक part जो कैसे दिखाता है।

Definition की आख़िरी line, "पाँच मिनट बाद नहीं", वह दर्द पहुँचाने वाली है। हमारे tests में, autoscaling पहला extra node लगभग सात मिनट बाद add करता था CPU 99% तक पहुँचने के बाद। सात मिनट लंबा समय है जब एक exam एक मिनट में शुरू होता है। Capacity cliff से पहले वहाँ होना चाहिए, बाद में नहीं।

पहले test: bottleneck बार-बार हटता है

Definition लिखने के बाद, हमने वह किया जो method चाहता है: पहले measure करो। सितंबर के अंत से 6 अक्टूबर तक हमने production को देखा और load test चलाए, और एक क्रम में तीन समस्याएँ पाईं। वे unrelated दिखते हैं, और यही बात है।

तीन bottleneck का timeline: 25 सितंबर को per-IP rate limiter code में fixed, 6 अक्टूबर को Valkey connection timeout resizing data tier से fixed, backend CPU capacity से solved
एक क्रम में तीन bottleneck, हर एक के साथ एक अलग तरह का fix। सिर्फ़ तीसरा ज़्यादा सर्वर से solve होता है।

1. Limiter: एक code समस्या (25 सितंबर)

Production पर measured: विद्यार्थियों को exams के दौरान HTTP 429 मिल रहे थे। Global API rate limiter IP से keyed था, क्योंकि default auth guard token-based विद्यार्थियों के लिए empty था, तो limiter नहीं बता सकता था कि एक विद्यार्थी कौन है। एक school या एक mobile carrier सैकड़ों विद्यार्थियों को एक NAT address के पीछे रखता है, और पूरी इमारत एक bucket share करती है।

Status: Implemented। हमने API limiter को per student या instructor account से keyed किया, और IP से सिर्फ़ guests के लिए। ज़्यादा सर्वर मदद नहीं देते; rule "no" कह रहा था, hardware नहीं। यह bug का एक क़रीबी cousin 7 अक्टूबर को route-level throttle में फिर से आया, और यह कहानी part 4 में है।

2. Valkey connections: एक data-tier sizing समस्या (6 अक्टूबर)

6 अक्टूबर को 02:28 पर, एक backend load test 2,854 application 500 error दे गया। हर एक RedisException: Operation timed out था जबकि connecting, 5 second connect timeout के साथ। Valkey (4 GB, primary plus standby) load के अंतर्गत connections को fast enough accept नहीं कर सकता था।

कैसे app ने इसे इस्तेमाल किया ने pressure add किया। हर request ने Valkey को (लगभग 5.4 ms CPU per request) और MySQL को (लगभग 3.3 ms) एक fresh TLS connection खोला। एक दुकान की कल्पना करें जहाँ हर customer को हर बार buzz किया और door पर check किया जाता है। एक भीड़ के अंतर्गत, door queue बन जाता है।

Status: Implemented, फिर Tested। हमने Valkey को in place resize किया 8 GB को दो nodes के साथ (primary और standby), data रखा गया और host unchanged। फिर हमने एक gradual ramp के साथ retest किया 25 से 500 requests per second तक, 2 backend nodes पर शुरू करते हुए जबकि pool scale out: 0 application error और 0 backend 5xx। Load balancer पर 143 error थे, लेकिन सिर्फ़ जबकि nodes CPU-saturated थे। यह expected "out of capacity" signal है, bug नहीं। Data tier को part 3 मिलता है, और Valkey part 4 में return करता है। General theory के लिए, data tier under load देखें।

3. Backend CPU: एक capacity समस्या

पहले दो fixed होने के बाद, जो रहा वह सिर्फ़ arithmetic था। एक 4 vCPU / 8 GB backend node लगभग 65 to 70 requests per second के असली API mix को serve करता है full CPU पर, लगभग 59 ms CPU per request। हर बाद का capacity decision इस नंबर पर बनाया गया है।

यह तीन bottleneck में से सिर्फ़ वह है जो ज़्यादा सर्वर सच में solve करते हैं, और यहाँ भी timing trap है: पहला extra node लगभग सात मिनट बाद आया CPU 99% को hit करने के बाद। कैसे हमने capacity जल्दी लाया यह part 2 का विषय है।

तो order था एक limiter (code), फिर Valkey connections (data-tier sizing), फिर backend CPU (capacity)। अगर हमने सर्वर add करके शुरू किया होता, limiter अब भी 429 कहता और Valkey अब भी timeout करता।

पुराने setup की लागत

नए shape के बारे में बात करने से पहले, यह जानना मदद करता है कि पुराना क्या cost करता था। ये पुराने web tier के लिए monthly DigitalOcean list prices हैं।

चीज़Costयह क्या खरीदता था
पुराना web tier: frontend, दो backend, worker, एक load balancer, दो standbysलगभग $416 एक महीने मेंएक running site कई single point of failure के साथ
दो powered-off standby droplet$112 एक महीने मेंकोई availability नहीं: off होने पर भी bill, ऊपर लाने में मिनट
एक extra backend node, comparison के लिएलगभग $0.08 एक घंटे मेंCapacity जो सच में requests serve करता है

$112, web tier का थोड़ा ऊपर एक चौथाई, वह नंबर है जो मेरे साथ रहा। यह दो सर्वर खरीदता था जो एक भी request serve नहीं कर सकते। एक extra backend node को pre-scale करना लगभग $0.08 एक घंटे में cost करता है, तो एक शाम के लिए capacity बढ़ाना cents cost करता है। महीना भर में ऐसी capacity के लिए pay करना जो switched off है safe महसूस करने का ज़्यादा महंगा तरीका है।

एक honest note: $416 सिर्फ़ web tier को cover करता है, database, Valkey या storage को नहीं, तो यह एक full bill के साथ compare नहीं हो सकता। Part 5 में मैं like को like के साथ compare करता हूँ।

Method, और series के लिए plan

Pattern जो हमने पूरे project में दोहराया वह जो आपने अभी देखा: measure, bottleneck ढूँढो, कारण समझो, architecture बदलो, फिर से test करो, और फिर से measure करो। ज़्यादा सर्वर जोड़ना architecture नहीं है। Architecture यह चुनना है कि कौन सी layer बदले, और क्यों।

यहाँ five part कैसे fit होते हैं।

PartLayerआप क्या देखेंगे
1 (यह part)Starting pointBusiness की समस्या, पुराना setup, high availability की definition, पहले bottleneck और पुरानी cost
2Application layerदो load balancer, दो autoscale pool, pre-scaling, image-based deploy और rollout lesson
3Databaseएक MySQL node से एक 26-minute window में एक primary with standby तक, read/write split, PostgreSQL with pgvector
4Valkey, worker, logQueue, worker, logging, monitoring और एक real exam के दौरान scale-in की गलती
5Proof7 अक्टूबर की real exam evening, load और soak testing, और final architecture

हमने भी ideas consider किए जो हमने build नहीं किए, और मैं हर एक को label करता हूँ। दोनों tier के लिए एक load balancer Considered था, फिर Rejected। एक "warm standby ready in seconds" Considered था, लेकिन autoscale pool के पास कोई warm pool नहीं है, तो हमने पहले से ही serving करने वाली spare capacity plus pre-scaling इस्तेमाल किए। Kubernetes बाद में Considered है और implemented नहीं है।

सब कुछ finished नहीं है, और मैं कहता हूँ। Single worker server एक known single point of failure है; इसे fix करना Planned है, नहीं done (part 4)। एक formal multi-hour soak test भी Planned है (part 5)।

क्या हम achieve करना चाहते थे

Checklist के रूप में goal, हर line के साथ जो part जो इसे build या test करता है।

  • Frontend और backend tier load balancer के पीछे, हर एक के साथ कम से कम दो node (part 2)।
  • नए सर्वर जो अपने आप join और छोड़ते हैं, कोई hand-edited node नहीं (part 2)।
  • Exam से पहले raised capacity, autoscaling safety net के रूप में (part 2 और 5)।
  • एक database एक standby के साथ जो एक बड़े single node से कम per month cost करता है (part 3)।
  • Web node जिनके पास कोई local state नहीं, तो submission किसी भी एक node के मरने से survive करते हैं (part 4)।
  • Deploy और scale-in जो विद्यार्थियों को नहीं दिखते (part 2 और 4)।
  • Capacity model real exam data से built (part 5)।
  • एक bill जिसे हम line by line explain कर सकते हैं (part 5)।

हमने क्या सीखा

  • "High availability" को failure और events के terms में लिख दो कुछ भी buy करने से पहले। एक definition जिसे आप एक सवाल से test कर सकते एक slogan से बेहतर है।
  • एक powered-off standby एक cost है, availability नहीं। हमारा availability के लिए कोई real protection के बिना $112 एक महीने में था।
  • Bottleneck हटता है। पहले को fix करने से अगला reveal होता है, तो हर change के बाद फिर से measure करो।
  • अलग bottleneck को अलग fix चाहिए: code (limiter), data-tier sizing (Valkey) और capacity (backend CPU)। सिर्फ़ आख़िरी ज़्यादा सर्वर से solve होता है।
  • Stateless node admission की क़ीमत हैं। उनके बिना, बाद के steps safe नहीं होते।

अगले, part 2 में, हम application layer build करते हैं: दो load balancer, दो autoscale pool, pre-scaling, और एक rollout method जो एक short 503 blip से सीखा गया।

About the Author

Anichur Rahaman

Continue Reading