- वास्तविक users बहुत कम होने के बावजूद बेकार की जटिल system architecture इस्तेमाल करने की समस्या की ओर इशारा
- Redis, MongoDB, Kubernetes, microservices जैसी कई technologies को बिना सोचे-समझे जोड़ने के उदाहरण प्रस्तुत
- ऐसी स्थिति पर ज़ोर जहाँ सिर्फ़ एक single Postgres instance और simple server setup ही काफ़ी था
- यह रेखांकित किया गया कि जटिलता कोई गुण नहीं है, और scale तभी करना चाहिए जब उसकी ज़रूरत साबित हो
- startup और development teams को अपनी scale के हिसाब से simple design principles अपनाने की याद दिलाने वाली बात
अनावश्यक technology stack का दुरुपयोग
- Redis और MongoDB को एक साथ इस्तेमाल करने जैसे बेतरतीब चुने गए technology combinations की आलोचना
- “Redis, MongoDB से बात क्यों कर रहा है?”, “MongoDB का उपयोग क्यों किया जा रहा है?” जैसे सवाल उठाए गए
- वास्तविक users सिर्फ़ 12 थे, जिनमें 6 test accounts थे, फिर भी distributed system लागू किया गया — इस पर सवाल
- इसे ऐसे उदाहरण के रूप में बताया गया जहाँ एक single Postgres instance पर्याप्त था, लेकिन फिर भी ज़रूरत से ज़्यादा scaling चुनी गई
deployment और infrastructure structure की अति
- मौजूदा setup: 15 microservices, 8 databases, 3 environments के Kubernetes clusters, 4 message queues, service mesh, 2 घंटे लेने वाली CI/CD pipeline
- जबकि आवश्यक setup के रूप में सिर्फ़ single server, Postgres, और caching के लिए Redis का सुझाव
- वास्तविक ज़रूरतों की तुलना में infrastructure complexity की अति को साफ़ तौर पर दिखाया गया
system complexity और explainability
- अगर किसी junior developer को system समझाने के लिए spaghetti की तरह उलझा diagram चाहिए, तो यह समस्या का संकेत है
- जटिलता कोई गुण नहीं है — इस वाक्य में मुख्य संदेश का सार
- सरलता से शुरू करने और ज़रूरत साबित होने पर ही complexity जोड़ने पर ज़ोर
मुख्य सीख
- technology choice और system design को scale और वास्तविक उपयोग के हिसाब से सरल रखना चाहिए
- बेतहाशा scaling और ज़रूरत से ज़्यादा technology stack अपनाना maintainability और efficiency को नुकसान पहुँचाता है
- startup या छोटी teams के लिए “अपनी scale के हिसाब से सरलता” बनाए रखना महत्वपूर्ण है
1 टिप्पणियां
Hacker News राय
कभी-कभी यह सब बस टालमटोल (procrastination) जैसा लगता है
ग्राहक, निवेशक, लीगल टीम जैसे लोगों से बात नहीं करनी, इसलिए उसकी जगह इंजीनियर की नज़र से ‘मज़ेदार काम’ कर लिया जाता है
ऊपर से यह प्रोडक्टिव दिखता है, लेकिन असल में वहीं के वहीं खड़े होते हैं
अगर हर दिन जानबूझकर कुछ असुविधाजनक काम न किए जाएँ, तो इंसान धीरे-धीरे कमजोर पड़ता जाता है, और बाद में ऐसे बड़े मसलों से टकराता है जिन्हें टाला जा सकता था
यह सिर्फ सॉफ्टवेयर पर नहीं, पूरी ज़िंदगी पर लागू होता है
पैसे कमाने के लिए मज़ेदार काम से ज़्यादा सही प्राथमिकता वाले काम करने पड़ते हैं, यह मैंने सीखा
कहीं यह वास्तविकता से कटे हुए CTO या VPE की ideal architecture वाली महत्वाकांक्षा को पूरा करने के लिए तो नहीं?
मुझे सिस्टम डिज़ाइन इंटरव्यू में monolithic vs microservices को लेकर माहौल भाँपने वाले खेल याद हैं
आखिर में जिन लोगों के पास अधिकार होता है, उन्हें किस दिशा में जाना है यह साफ़ होता है, और उसके खिलाफ जाना राजनीतिक पूंजी जलाने जैसा है
“मैंने ABC और XYZ को जोड़कर देखा है” जैसी शैली में अपना tech stack गिनाना शुरू कर देते हैं
रेज़्यूमे को शानदार दिखाने की चाह भी होती है
सच तो यह है कि ज़्यादातर प्रोजेक्ट 1990 के दशक की तकनीक से भी आराम से बन सकते हैं, लेकिन अगर उसमें distributed systems जैसे शब्द हों तो वह कहीं ज़्यादा ‘कूल’ लगता है
इंडस्ट्री की खराब hiring culture की वजह से हाल यह है कि जैसे किसी शेफ को चाकू अच्छी तरह चलाने से ज़्यादा ‘किसी खास ब्रांड के चाकू’ का इस्तेमाल करना ज़रूरी मान लिया जाए
उदाहरण के लिए DuckDuckGo सिर्फ algorithms और data structures मांगता है, और बस इतना कहता है कि “वैसे हम Perl इस्तेमाल करते हैं”
Stream, Go न जानने वाले उम्मीदवारों को 10 हफ्ते का कोर्स देता है, और Jane Street भी OCaml अनुभव अनिवार्य नहीं करता
जहाँ मैं काम करता हूँ, bevuta IT GmbH ने भी जॉइन करने के बाद Clojure सीखने का मौका दिया
यह तरीका “Ruby on Rails में 10 साल का अनुभव” जैसी पुरानी जॉब पोस्टिंग से बिल्कुल अलग है
क्योंकि मैं कुछ नया आज़माना और तुलना करना चाहता था
आखिरकार कुछ सौ users के लिए भी अनावश्यक जटिलता पर बात करना इंडस्ट्री की हकीकत बन चुका है
“Redis से caching” कहना बहुत आम है, लेकिन सच में Postgres से भी काम चल सकता है
Redis इस्तेमाल करने पर ज़ोर देना शायद लेखक की अपनी overengineering की इच्छा को भी पूरी तरह काबू न कर पाने जैसा है
छोटे scale पर caching की ज़रूरत ही नहीं होती, और temporary data को अलग सिस्टम में रखना ज़्यादा आकर्षक है
framework की cache abstraction भी ज़्यादातर Redis को ध्यान में रखकर ही डिज़ाइन की जाती है
शुरुआत में in-memory cache से शुरू करना और ज़रूरत पड़ने पर Redis जोड़ना बेहतर है
लेकिन Redis/Valkey ज़रूरत से ज़्यादा है। memcached कहीं ज़्यादा सरल और व्यावहारिक है
Redis की तरह state persist नहीं करता, इसलिए cache consistency पर निर्भर खराब design pattern से बचा जा सकता है
DB cache को file system से होकर गुजरना पड़ता है, इसलिए वह धीमा होता है
queries को कुशल बनाना एक बिल्कुल अलग समस्या है
Postgres को फिर से तेज़ कर देने के बाद Redis हटाया भी जा सकता है, लेकिन आमतौर पर लोग उसे वैसे ही छोड़ देते हैं
AWS Lambda-आधारित web app में प्रति सेकंड 1000 requests सँभालते समय Postgres संघर्ष कर रहा था, लेकिन Redis आराम से चल रहा था
अपनी सरलता की वजह से कुछ खास परिस्थितियों में इसका इस्तेमाल वाजिब है
मज़ेदार बात यह है कि लेखक “सरलता” की बात करता है, फिर भी उसने पेज Tailwind + JS framework + bundler से बनाया
जबकि वह इसे साधारण HTML से भी बना सकता था
इसलिए मैं ऐसा सरल web framework MastroJS परिचय नहीं, बल्कि परिचय कराता हूँ जिसे आप खुद समझकर बना सकते हैं
व्यवहार में यह सिर्फ इस्तेमाल किए गए utility classes के लिए CSS बनाता है
मूल ट्वीट Jeff Atwood के 2013 के ट्वीट से आया था
मैं अभी खुद भी इसी तरह के फैसले पर सोच रहा हूँ
अगर प्रोडक्ट का market validation नहीं हुआ है, तो छोटा और तेज़ शुरू करके pivot किया जा सकने वाला MVP बनाना सही है
दूसरी तरफ, अगर आपको निवेशकों या बड़े enterprise ग्राहकों को scalable design capability दिखानी है, तो शुरुआत से scale हो सकने वाली संरचना चुननी होगी
अगर business model तभी काम करेगा जब वह एक single DB से संभलने से बहुत आगे बढ़े, तो शुरुआत से scalable architecture लेना लंबी अवधि में फायदेमंद है
जो लोग infra nightmare के बीच काम करते हैं, उनके लिए simplicity की बात खोखली लग सकती है
लेकिन बहुत-सी जटिलता तकनीकी से ज़्यादा organizational problems सुलझाने के लिए होती है
deployment automation, failures के लिए redundancy, CI pipeline, secrets management, caching वगैरह टीम को बचाने वाले safety mechanism हैं
टीम स्तर पर काम करते समय इन्हें नज़रअंदाज़ करना जोखिम भरा है
SQLite भी production में ठीक से इस्तेमाल हो सकता है, लेकिन “सिर्फ testing के लिए” वाला पूर्वाग्रह फैला हुआ है
कई बार PaaS की default settings ही अनावश्यक रूप से जटिल होती हैं
checklist-आधारित build process से शुरू करें, और उसके स्थिर हो जाने पर automation की तरफ बढ़ें
मैं FAANG स्तर के बाहर ऐसे उदाहरण देखना चाहूँगा जहाँ microservices सच में ज़रूरी हों
सोचने से डरकर सब लोग बस standard tech stack के पीछे चल पड़ते हैं
Kafka, Mongo, Redis जैसी चीज़ों का बिना सोचे-समझे इस्तेमाल करना ही समस्या है
असल में सिर्फ ज़रूरी features खुद बनाना बेहतर हो सकता है, और न्यूनतम components चुनने की क्षमता ही इंजीनियर की असली ताकत है
Kafka जैसी चीज़ें कई बार यूँ ही पैसे की बर्बादी होती हैं
“ज़रूरत पड़ने पर ही complexity जोड़ो” यह बात सही है, लेकिन कुछ चीज़ें बाद में जोड़ना मुश्किल होता है
अगर शुरुआती डिज़ाइन गलत हो, तो पूरा rewrite करना पड़ सकता है
इसलिए व्यवहारिक रूप से सरल k8s configuration जैसी मध्य-रेखा की ज़रूरत पड़ती है
हाल की एक इंटरव्यू में भी मेरा ऐसा ही अनुभव रहा
पिछले 10 सालों में मैं PMF(Product-Market Fit) हासिल करने पर केंद्रित रहा, शुरुआत से scalability पर अटका नहीं रहा
अगर product market में fit बैठता है, तो scalability की समस्या को पैसे से हल किया जा सकता है
लेकिन इंटरव्यू में जब पूछा गया कि “Django service को दिन में 1 करोड़ requests तक कैसे scale करोगे”
तो मैंने जवाब दिया, “server specs बढ़ा दीजिए,” और लगता है उन्हें यह जवाब संतोषजनक नहीं लगा