अपने सर्वर पर चलने वाले कॉमर्स प्लेटफ़ॉर्म को स्केल करना: रोज़ 100 से 1,00,000 ऑर्डर तक का सर्वर रोडमैप
कॉमर्स इन्फ्रास्ट्रक्चर को चरण-दर-चरण बढ़ाने की गाइड: हर चरण में क्या जोड़ें, कौन-से मेट्रिक बताते हैं कि कब, सबसे पहले क्या टूटता है, बिना डाउनटाइम blue/green deploy, और ऐसे बैकअप जिन्हें सच में रिस्टोर किया जा सके।
Author
Anichur Rahaman

लगभग हर सेल्फ़-होस्टेड कॉमर्स प्लेटफ़ॉर्म की शुरुआत एक जैसी होती है: एक सर्वर, एक डेटाबेस और एक व्यक्ति जिसे पता है कि कौन-सी चीज़ कहाँ है। शुरुआत का यही सही तरीक़ा है — कम ख़र्च, कम झंझट, और पहले हज़ार-डेढ़ हज़ार ग्राहकों के लिए रफ़्तार भी पर्याप्त।
दिक़्क़त तब शुरू होती है जब आर्किटेक्चर बदलने से पहले ही बिज़नेस बढ़ जाता है। एक फ़्लैश सेल से किसी दोपहर ट्रैफ़िक दोगुना हो जाता है। कूरियर इंटीग्रेशन हर कुछ सेकंड में रिक्वेस्ट दोहराता रहता है। लंच के व्यस्त समय में कोई दो साल के ऑर्डर पर फ़ाइनेंस रिपोर्ट चला देता है। अचानक चेकआउट धीमा हो जाता है, और किसी को समझ नहीं आता कि क्यों।
कॉमर्स और ERP सिस्टम का इन्फ्रास्ट्रक्चर प्लान करते समय मैं जिस स्केलिंग रोडमैप पर चलता हूँ, यह लेख वही है। इसे चार चरणों में बाँटा गया है — रोज़ लगभग 100 ऑर्डर से लेकर 1,00,000 और उससे आगे तक। हर चरण में बताया गया है कि क्या जोड़ना है, क्या नापना है, और सबसे ज़रूरी — सबसे पहले क्या टूटता है। मक़सद यही है कि आर्किटेक्चर तब बदलें जब आँकड़े कहें, ग्राहक की शिकायत के बाद नहीं।

पहला सिद्धांत: स्केल करने से पहले नापिए
स्केलिंग महँगी है, और हर नया पुर्ज़ा ख़राब होने की एक और जगह है। नया सर्वर ख़रीदने से पहले पक्का कीजिए कि ये पाँच आँकड़े आपके डैशबोर्ड पर दिख रहे हैं:
- p95 रिस्पॉन्स टाइम — होम पेज, प्रोडक्ट पेज, कार्ट और चेकआउट का। औसत उन धीमी रिक्वेस्ट को छिपा देता है जिनमें बिक्री हाथ से निकल जाती है।
- डेटाबेस पर दबाव — कितने कनेक्शन सक्रिय हैं, धीमी क्वेरी (100 मिलीसेकंड से ज़्यादा लेने वाली कोई भी), और cache hit ratio।
- queue की लंबाई और उम्र — कितने job इंतज़ार में हैं, और सबसे पुराना कितनी देर से रुका है।
- हर सर्वर की मेमोरी और swap, साथ में kernel लॉग में मेमोरी ख़त्म होने से प्रोसेस बंद होने (OOM kill) की घटनाएँ।
- एरर रेट — हर मिनट कितने 5xx रिस्पॉन्स, हर घंटे कितने job फ़ेल।
अगर ये आँकड़े दिख नहीं रहे, तो पहला स्केलिंग प्रोजेक्ट मॉनिटरिंग ही है। जिस सर्वर की हालत आप देख नहीं सकते, उसे आप ज़रूरत से ज़्यादा ही ख़रीदेंगे।
चरण 1 — एक ही सर्वर पर सब कुछ (रोज़ ~1,000 ऑर्डर तक)
4 vCPU, 8 जीबी रैम और तेज़ SSD वाला एक वर्चुअल सर्वर उम्मीद से कहीं बड़ा बिज़नेस संभाल लेता है। Docker container से इसे व्यवस्थित रखिए: वेब (nginx के पीछे PHP-FPM), PostgreSQL, Redis, एक queue worker और एक scheduler।
इस चरण में क्या ठीक रखना है
- OPcache चालू, preload के साथ। PHP हर फ़ाइल एक बार कम्पाइल करके मेमोरी में रख लेता है। कई बार सिर्फ़ इसी से रिस्पॉन्स टाइम आधा हो जाता है।
- provider boot में कोई काम नहीं। जो कुछ हर रिक्वेस्ट पर चलता है (सेटिंग्स पढ़ना, मेनू बनाना), उसे cache कीजिए। हर रिक्वेस्ट पर 10 मिलीसेकंड बड़े स्केल पर पूरा एक CPU core खा जाते हैं।
- धीमे काम background में। ईमेल, कूरियर बुकिंग, इमेज रीसाइज़ और PDF इनवॉइस queue में जाएँ — चेकआउट की रिक्वेस्ट के अंदर कभी नहीं।
- सर्वर से बाहर बैकअप, और जाँचा हुआ। हर रात डेटाबेस का डंप object storage में, और महीने में एक बार रिस्टोर करके देखना। जिस बैकअप को कभी रिस्टोर करके नहीं देखा, वह सिर्फ़ उम्मीद है — बैकअप नहीं।
सबसे पहले क्या टूटता है
मेमोरी। भारी रिपोर्ट, बड़ा इम्पोर्ट या ढेर सारी इमेज का काम चेकआउट के साथ रैम के लिए होड़ करता है। लक्षण होते हैं बेतरतीब धीमे पेज, और आख़िर में kernel किसी प्रोसेस को बंद कर देता है। scheduler अक्सर इसका शिकार बनता है: उसे अलग मेमोरी लिमिट दीजिए (512 एमबी एक समझदार न्यूनतम सीमा है), और हर मिनट नया प्रोसेस शुरू करने की जगह एक लगातार चलने वाला scheduler प्रोसेस रखिए।
चरण 2 — काम के हिसाब से बँटवारा (रोज़ ~1,000 से 10,000 ऑर्डर)
अगला कदम "वही सर्वर, बस बड़ा वाला" नहीं है। अगला कदम है कामों को अलग करना, ताकि वे संसाधनों के लिए आपस में न लड़ें।
| काम | अलग क्यों | आम साइज़ |
|---|---|---|
| डेटाबेस सर्वर | अपनी डिस्क I/O और cache के लिए अपनी मेमोरी; किसी पड़ोसी के दबाव का असर नहीं। | 4–8 vCPU, 16–32 जीबी रैम, NVMe |
| Redis सर्वर | दबाव में भी session, cache और queue तेज़ रहते हैं। | 2 vCPU, 4–8 जीबी रैम |
| वेब नोड | PHP का काम ज़्यादातर CPU पर टिका है; इसे अलग से बढ़ाया जा सकता है। | हर एक 2–4 vCPU |
| queue worker | हर queue का अलग worker pool, ताकि ईमेल की भीड़ में पेमेंट न अटके। | हर pool में 2 vCPU |
विज़िटर जो पेज देखते हैं, उन्हें cache कीजिए
स्टोर का ज़्यादातर ट्रैफ़िक बिना लॉगिन वाला होता है — लोग प्रोडक्ट और कैटेगरी देख रहे होते हैं। इन पेजों को कुछ मिनटों के लिए पूरे HTML के रूप में ऐप्लिकेशन और CDN पर cache किया जा सकता है। दो नियम बड़ी परेशानी से बचाते हैं:
- cache key में डोमेन का नाम ज़रूर हो। अगर स्टोर दो डोमेन पर चलता है, तो बिना डोमेन वाली key एक डोमेन के लिंक और स्क्रिप्ट दूसरे डोमेन के विज़िटर को दिखा देगी।
- निजी जानकारी कभी cache नहीं। कार्ट में कितने आइटम, लॉग-इन ग्राहक के ख़ास दाम, अकाउंट पेज — ये cache किए गए ढाँचे के बाद अलग से लोड हों, या बिल्कुल cache न हों।
सबसे पहले क्या टूटता है
डेटाबेस कनेक्शन और धीमी क्वेरी। हर PHP worker अपना कनेक्शन खोलता है। दो वेब नोड पर चालीस worker और साथ में queue worker मिलकर PostgreSQL की आरामदायक सीमा आसानी से पार कर जाते हैं। उसी समय, टेबल में दस लाख से ज़्यादा पंक्तियाँ होने पर एक ग़ायब index 5 मिलीसेकंड की क्वेरी को 900 मिलीसेकंड की बना देता है। हर हफ़्ते slow query log देखने की आदत डालिए।
चरण 3 — स्केल आउट (रोज़ ~10,000 से 50,000 ऑर्डर)
अब एक load balancer के पीछे कई एक जैसे वेब नोड चलेंगे। शर्त बस एक है — वेब लेयर पर कोई स्टेट नहीं रहेगी: session Redis में, अपलोड की गई फ़ाइलें object storage में, किसी भी वेब नोड की अपनी डिस्क पर कुछ भी ज़रूरी नहीं।

इस चरण में सबसे ज़्यादा काम आने वाली चीज़ें
- कनेक्शन पूलिंग (PgBouncer)। सैकड़ों ऐप कनेक्शन मिलकर कुछ दर्जन असली डेटाबेस कनेक्शन बाँट लेते हैं। स्थिरता के लिहाज़ से अक्सर यही सबसे बड़ा सुधार होता है।
- रिपोर्ट के लिए read replica। डैशबोर्ड, एक्सपोर्ट और एनालिटिक्स replica से पढ़ेंगे, इसलिए भारी रिपोर्ट चेकआउट को धीमा नहीं करेगी।
- इमेज और बैकअप के लिए object storage। S3 या Cloudflare R2 जैसी सेवा, CDN के ज़रिए परोसी गई। वेब नोड को इमेज भेजने का काम ही नहीं करना पड़ता।
- अलग SSR सर्वर। server-side rendering पेज को तेज़ और सर्च इंजन के अनुकूल बनाता है, लेकिन इसका काम PHP से अलग किस्म का है। इसे अलग से स्केल कीजिए।
- queue पर नज़र। Laravel Horizon जैसा डैशबोर्ड, जिसमें हर queue की रफ़्तार, विफलताएँ और इंतज़ार का समय दिखे — अलर्ट के साथ।
सबसे पहले क्या टूटता है
cache stampede और hot row। किसी लोकप्रिय cache की मियाद ख़त्म होते ही सैकड़ों रिक्वेस्ट एक ही पल में उसे दोबारा बनाने दौड़ पड़ती हैं। lock या "stale-while-revalidate" का इस्तेमाल कीजिए — एक रिक्वेस्ट नया बनाए, बाक़ी तब तक पुराना मान दिखाएँ। दूसरी समस्या वह पंक्ति है जिसे हर कोई अपडेट कर रहा है — फ़्लैश सेल वाले प्रोडक्ट का स्टॉक काउंटर या कोई सीरियल नंबर। वहाँ ट्रांज़ैक्शन कतार में खड़े हो जाते हैं। ऐसे अपडेट छोटे और atomic रखिए।
चरण 4 — पूरा फ़्लीट (रोज़ 50,000+ ऑर्डर)
इस पैमाने पर तकनीकी तरीक़े सबको पता होते हैं। जो बदलता है, वह है उनके इर्द-गिर्द का अनुशासन:
- बँटी हुई queue, ताकि पेमेंट, नोटिफ़िकेशन, सर्च इंडेक्सिंग और AI के कामों को अपनी-अपनी अलग क्षमता मिले।
- सर्च और एनालिटिक्स अलग इंजन पर — उन्हीं के लिए बने इंजन, जिन्हें जानकारी event से मिले, रात के डंप से नहीं।
- पुराने डेटा के लिए आर्काइव स्टोरेज। पुराने ऑर्डर, लॉग और ऑडिट ट्रेल सस्ते स्टोरेज में चले जाते हैं, फिर भी ज़रूरत पड़ने पर खोजे जा सकते हैं।
- कई रीजन में edge — स्टैटिक फ़ाइलें और cache किए गए पेज ग्राहक के सबसे नज़दीक से।
- runbook और on-call। हर अलर्ट के लिए पहले से लिखा हो कि सबसे पहले क्या करना है। मैंने जो सबसे बुरे आउटेज देखे, वे सर्वर की कमी से नहीं हुए — इसलिए हुए कि रात 3 बजे किसी को पता नहीं था कि क्या करना है।
बिना डाउनटाइम के deploy: blue/green
जो स्टोर हर रिलीज़ पर ऑफ़लाइन होता है, वहाँ टीम धीरे-धीरे कम रिलीज़ करना सीख जाती है — और इससे हर रिलीज़ और जोखिम भरी हो जाती है। blue/green deployment इस चक्र को तोड़ता है।

- बिल्ड एक बार। हर commit की एक image, CI में जाँची हुई; staging से production तक वही image बिना बदले जाती है।
- green चालू कीजिए चल रहे blue container के बगल में।
- migration सिर्फ़ जोड़ने वाला। नए कॉलम और टेबल जोड़िए; उसी रिलीज़ में नाम बदलना या हटाना नहीं। पुराना कोड नई स्कीमा के साथ भी चलता रहे।
- वार्म-अप और जाँच। config और route cache कीजिए, health endpoint पर रिक्वेस्ट भेजिए, एक छोटा smoke test चलाइए।
- स्विच कीजिए गेटवे का upstream बदलकर — reload से, restart से नहीं, ताकि एक भी कनेक्शन न टूटे।
- blue को बनाए रखिए तुरंत rollback के लिए। पुराने कॉलम किसी अगली रिलीज़ में हटाइए, जब कोई उन्हें पढ़ न रहा हो।
ठोकर खाकर सीखा सबक़: नया वर्ज़न तैयार करते समय चालू वर्ज़न का cache या कम्पाइल की हुई फ़ाइलें साफ़ कर दीं, तो हर deploy पर कुछ रिक्वेस्ट फ़ेल होंगी। नई रिलीज़ उसकी अपनी डायरेक्टरी में तैयार कीजिए, और ऐप का cache सिर्फ़ एक बार साफ़ कीजिए — स्विच के ठीक बाद।
बैकअप, RPO और RTO — आसान भाषा में
दो आँकड़े आपकी बैकअप रणनीति तय करते हैं, और इन्हें बिज़नेस तय करे — IT टीम नहीं:
- RPO (Recovery Point Objective): ज़्यादा से ज़्यादा कितना डेटा खोना मंज़ूर है। रात में एक बार बैकअप का मतलब है अधिकतम 24 घंटे के ऑर्डर खोने का जोखिम।
- RTO (Recovery Time Objective): रिस्टोर के दौरान साइट ज़्यादा से ज़्यादा कितनी देर बंद रह सकती है।
| चरण | समझदार RPO | समझदार RTO | कैसे |
|---|---|---|---|
| 1 | 24 घंटे | 4 घंटे | रात में डेटाबेस डंप और फ़ाइलें, object storage में |
| 2 | 1 घंटा | 1 घंटा | हर घंटे snapshot, स्क्रिप्ट से रिस्टोर |
| 3–4 | कुछ मिनट | 30 मिनट से कम | लगातार WAL archiving, standby replica |
जो भी चुनें, रिस्टोर टेस्ट की एक तय तारीख़ रखिए। StoreConsole का Backup मॉड्यूल तय समय पर डेटाबेस और फ़ाइलों का snapshot लेता है, डिस्क की हालत जाँचता है, कितने दिन रखना है वह नियम मानता है और एक क्लिक में रिस्टोर करता है। नीचे का छोटा वीडियो यही दिखाता है।
पाँच ग़लतियाँ जो मैं बार-बार देखता हूँ
- CDN पर 404 cache हो जाना। अगर किसी पेज के माँगने के बाद इमेज अपलोड की, तो CDN घंटों तक "नहीं मिला" दिखा सकता है। पहले फ़ाइल रखिए, फिर लिंक दीजिए।
- एक डेटाबेस पर पास, दूसरे पर फ़ेल। टेस्ट में SQLite और production में PostgreSQL — case-sensitive सर्च, टाइप की तुलना और enum बदलाव पर दोनों अलग बर्ताव करते हैं। कम से कम एक CI job production वाले डेटाबेस पर ही चलाइए।
- production सर्वर पर भारी बिल्ड। एक साथ दो asset बिल्ड मेमोरी ख़त्म करके स्टोर गिरा सकते हैं। बिल्ड CI में कीजिए, सर्वर पर तैयार image भेजिए।
- सामान्य shell में "&" से चलाए background प्रोसेस। session ख़त्म होते ही ये बंद हो जाते हैं। supervisor या container runtime इस्तेमाल कीजिए।
- production में debug टूल चालू छूट जाना। query listener और profiler हर रिक्वेस्ट पर अतिरिक्त काम जोड़ते हैं, और भूला हुआ कोई monitor हफ़्तों तक चुपचाप पूरा एक CPU खा सकता है।
आज ही इस्तेमाल करने लायक चेकलिस्ट
- सबसे व्यस्त घंटे में चेकआउट का p95 समय 800 मिलीसेकंड से कम।
- पीक पर डेटाबेस CPU 60% से कम; चेकआउट के रास्ते में कोई क्वेरी 100 मिलीसेकंड से ज़्यादा नहीं।
- पेमेंट और नोटिफ़िकेशन की queue में सबसे पुराना job 60 सेकंड से कम पुराना।
- पीक पर हर सर्वर पर कम से कम 30% मेमोरी ख़ाली; पिछले हफ़्ते एक भी OOM kill नहीं।
- आख़िरी रिस्टोर टेस्ट पिछले 30 दिनों के अंदर।
- हर रिलीज़ बिना डाउनटाइम deploy हो सके, और ज़रूरत पड़ने पर वापस ली जा सके।
अगर आप ख़ास तौर पर StoreConsole के लिए हार्डवेयर प्लान कर रहे हैं, तो हर चरण के सुझाए साइज़ सिस्टम रिक्वायरमेंट्स पेज पर हैं, और Docker, queue व scheduler की जानकारी डॉक्यूमेंटेशन में है।
सार
- तब स्केल कीजिए जब आँकड़े कहें: p95 लेटेंसी, डेटाबेस पर दबाव, queue का इंतज़ार, मेमोरी और एरर रेट।
- चरण 1 है अच्छी तरह ट्यून किया एक सर्वर। चरण 2 काम बाँटता है। चरण 3 pooling, replica और object storage से फैलता है। चरण 4 मुख्य रूप से अनुशासन का मामला है।
- धीमे काम रिक्वेस्ट के रास्ते से दूर रखिए; ख़रीदार को कभी queue job का इंतज़ार न करना पड़े।
- सिर्फ़ जोड़ने वाले migration के साथ blue/green deploy कीजिए, और rollback के लिए पिछला वर्ज़न तैयार रखिए।
- RPO और RTO बिज़नेस तय करे, फिर नियम से रिस्टोर टेस्ट कीजिए।
अनिचुर रहमान सॉफ़्टवेयर आर्किटेक्ट और StoreConsole के संस्थापक हैं। वे बढ़ते बिज़नेस के लिए कॉमर्स और ERP सिस्टम डिज़ाइन करते हैं — ख़ास ध्यान event-driven आर्किटेक्चर, डेटा की सटीकता और अपने ही सर्वर पर चलने वाले सिस्टम पर।
About the Author
Anichur Rahaman

