GraphQL: एंटरप्राइज़ का हनीमून खत्म हो चुका है
(johnjames.blog)- GraphQL डेटा की overfetching समस्या को हल करने की कोशिश करता है, लेकिन ज़्यादातर एंटरप्राइज़ माहौल में यह समस्या पहले ही दूसरे तरीकों से हल की जा चुकी होती है
- BFF(Backend for Frontend) संरचना वाले सामान्य कॉर्पोरेट सिस्टम में GraphQL के मुख्य फायदे काफी कम हो जाते हैं
- इम्प्लिमेंटेशन की जटिलता, observability में गिरावट, caching की समस्याएँ, ID constraints, और file handling की असुविधा के कारण वास्तविक production environment में इसकी लागत बढ़ जाती है
- REST सरल, तेज़ है, और error handling व onboarding आसान बनाता है, इसलिए बड़े टीम माहौल में यह ज़्यादा प्रभावी है
- निष्कर्षतः, GraphQL कुछ खास स्थितियों में उपयोगी है, लेकिन ज़्यादातर एंटरप्राइज़ के लिए यह एक overkill विकल्प माना जाता है
GraphQL जिस समस्या को हल करना चाहता है
- GraphQL का मुख्य उद्देश्य overfetching (ज़रूरत से ज़्यादा डेटा मंगाना) को रोकना है
- क्लाइंट केवल वही fields request कर सकता है जिनकी उसे ज़रूरत है, जिससे अनावश्यक डेटा ट्रांसफर कम होता है
- हर नए UI requirement पर backend बदलने की ज़रूरत नहीं पड़ती, यह इसका एक लाभ है
- लेकिन वास्तविक माहौल में यह आदर्श संरचना जटिल वास्तविकताओं से मेल नहीं खाती
BFF के कारण overfetching पहले ही हल हो चुका है
- ज़्यादातर एंटरप्राइज़ फ्रंटएंड में BFF(Backend for Frontend) लेयर का उपयोग होता है
- यह UI के अनुसार डेटा को जोड़ती है, कई downstream calls को समेटती है, और backend की जटिलता को छिपाती है
- REST-आधारित BFF पहले से ही सिर्फ़ ज़रूरी डेटा लौटा सकता है, इसलिए GraphQL का लाभ दोहराव जैसा बन जाता है
- अगर GraphQL लेयर REST API से डेटा ला रही हो, तो overfetching बस एक स्तर नीचे खिसक जाता है
- कई pages अगर एक ही endpoint साझा करते हों, तब GraphQL उपयोगी हो सकता है, लेकिन
- उसका लाभ अक्सर कुछ kilobytes बचाने के लिए ज़्यादा setup और maintenance burden उठाने जितना ही होता है
इम्प्लिमेंटेशन जटिलता और उत्पादकता में कमी
- GraphQL, REST की तुलना में काफ़ी अधिक समय और जटिलता माँगता है
- schema, type, resolver, data source definitions जैसी अतिरिक्त चीज़ें बनानी पड़ती हैं
- schema और client के बीच sync बनाए रखने का भी बोझ रहता है
- GraphQL consumption (क्लाइंट सुविधा) को optimize करता है, लेकिन production (server development speed) की क़ीमत पर
- एंटरप्राइज़ माहौल में development speed और simplicity ज़्यादा महत्वपूर्ण होते हैं
Observability और monitoring की समस्या
- GraphQL का HTTP status code system एकसमान नहीं होता
- 200 response में भी errors हो सकती हैं, इसलिए monitoring में success/failure अलग करना मुश्किल हो जाता है
- REST में 2XX/4XX/5XX का साफ़ विभाजन होता है, जिससे dashboard filtering सहज रहती है
- Apollo आदि में customization संभव है, लेकिन इससे अतिरिक्त setup और मानसिक बोझ बढ़ता है
- production incident के दौरान REST की तुलना में समस्या पहचानना ज़्यादा कठिन और जटिल हो जाता है
Caching की व्यावहारिक सीमाएँ
- Apollo की normalized caching सिद्धांत में शक्तिशाली लगती है, लेकिन व्यवहार में नाज़ुक और जटिल साबित होती है
- सिर्फ़ एक field अलग होने पर भी queries अलग मानी जाती हैं, इसलिए manual linking करनी पड़ती है
- cache debugging अपने आप में एक अलग समस्या बन जाती है
- इसके विपरीत REST पूरे response को cache करके ज़्यादा स्थिर और maintainable रहता है
ID field constraints की समस्या
- Apollo मानकर चलता है कि हर object में id या _id field होगी
- कई एंटरप्राइज़ APIs में unique ID होती ही नहीं, या वह global identifier नहीं होती
- इसे संभालने के लिए BFF को local ID generation logic जोड़ना पड़ता है
- नतीजतन अनावश्यक fields और logic बढ़ जाते हैं, और overfetching घटाने का लाभ भी कम हो जाता है
File upload और download की अक्षमता
- GraphQL binary data handling के लिए उपयुक्त नहीं है
- व्यवहार में download URL लौटाया जाता है, और file transfer REST से होता है
- PDF जैसे बड़े डेटा को GraphQL response में शामिल करने पर performance गिरती है
- इससे GraphQL के “single API” वाले आदर्श को झटका लगता है
Onboarding और learning curve
- ज़्यादातर developers के पास REST का अच्छा अनुभव होता है, लेकिन GraphQL के लिए अलग learning चाहिए
- schema, resolver, query composition, caching rules, error handling जैसे नए concepts सीखने पड़ते हैं
- इससे team onboarding की गति धीमी पड़ती है
- REST एक “उबाऊ लेकिन highly scalable” approach की तरह बड़ी टीमों के लिए ज़्यादा उपयुक्त है
Error handling की जटिलता
- GraphQL error responses में nullable fields, partial data, errors array, extended status codes जैसी जटिलताएँ होती हैं
- यह भी ट्रैक करना पड़ता है कि कौन-सा resolver fail हुआ
- REST में 400/500 जैसे सीधे विभाजन के कारण समझना और debugging आसान रहती है
निष्कर्ष: GraphQL एक niche तकनीक है
- GraphQL कुछ खास स्थितियों में एक वैध टूल है
- लेकिन ज़्यादातर एंटरप्राइज़ माहौल में समस्याएँ पहले ही BFF और REST से हल की जा चुकी होती हैं
- मुख्य चुनौती overfetching नहीं, बल्कि observability, reliability, और speed होती है
- नतीजतन GraphQL एक संकीर्ण समस्या हल करते हुए व्यापक जटिलता पैदा करता है
- निष्कर्ष यह है: “GraphQL बुरा नहीं है, लेकिन ज़्यादातर मामलों में इसकी ज़रूरत नहीं है”
2 टिप्पणियां
Hacker News की राय
मैं इस बात से सहमत नहीं हूँ कि GraphQL की मुख्य समस्या overfetching है
मेरे हिसाब से इसकी असली ताकत यह है कि (a) यह सख्त type-based contract लागू करता है, और (b) schema evolution को काफी आसान बनाता है
type system की वजह से input और output हमेशा एक तय shape का पालन करते हैं, और custom scalar types (जैसे: phone number, email आदि) इस्तेमाल करने पर bugs और security issues काफी कम हो सकते हैं
साथ ही, नए fields जोड़ना या पुराने fields को deprecate करना standardized होता है, इसलिए server और client दोनों पर cognitive load कम रहता है
मैं GraphQL का उपयोग API composition और evolution की वजह से करता हूँ। खासकर M:N संरचना वाले बड़े systems में “client जो चाहिए उसे describe करे → server compose करे → domain service उसे solve करे” वाला flow लंबे समय में काफी ज़्यादा manageable होता है
अच्छी observability के साथ मिलकर यह data access की एक मजबूत नींव बन जाता है
एक और फायदा है resolver reuse और federation का आसान होना। REST में यह काफी झंझटी है
schema evolution को Protobuf भी अच्छी तरह संभालता है
GraphQL का असली फायदा यह है कि UI data को छोटे-छोटे हिस्सों में compose किया जा सकता है
इस वीडियो की तरह अगर fragment colocation का उपयोग किया जाए, तो child components में बदलाव करने पर बाकी हिस्सों पर असर नहीं पड़ता
queries fragment-based तरीके से अपने आप generate हो जाती हैं, इसलिए field हटाने पर दूसरे components के टूटने का जोखिम भी कम हो जाता है
अगर scale छोटा हो या तेज development इतना महत्वपूर्ण न हो, तो GraphQL overinvestment जैसा लग सकता है
Colocation वाकई एक revolutionary concept है, लेकिन Apollo ने इसका लगभग ज़िक्र ही नहीं किया
Relay की documentation अब भी कमजोर है, लेकिन Entrypoint का concept शानदार है
लेकिन graphql-codegen का implementation plugin compatibility के मामले में कमजोर है, इसलिए हमें अपना plugin खुद बनाना पड़ा
पूरे ecosystem में consistency की कमी है
यह कहना कि overfetching GraphQL की मुख्य समस्या है, बढ़ा-चढ़ाकर कहना है
मुझे लगता है GraphQL वह tool है जो ORM द्वारा हल किए जाने वाले impedance mismatch को client level पर संभालता है
Relay जैसे compiler-based tooling के बिना इसका उपयोग करना एक antipattern है
आजकल AI data layer अपने आप generate कर देता है, इसलिए GraphQL की ज़रूरत कम होती दिख रही है
अगर आप कोई non-existent field चुनते हैं तो यह उसे अपने आप generate भी कर देता है, यानी developer experience (DevEx) बेहतरीन है
modern web की धीमी गति का बड़ा कारण ज़रूरत से ज़्यादा data transfer है। वास्तव में कई apps 0.5% से भी कम efficiency पर चलते हैं
मैं 2016 से GraphQL इस्तेमाल कर रहा हूँ
मूल रूप से GraphQL एक RPC spec है। इसे server के “Action(Args) → ResultType” map के रूप में implement किया जाता है
REST के कई endpoints के बजाय, GraphQL एक
/queryendpoint पर resolver map के ज़रिए काम करता हैअंततः यह OpenAPI या gRPC की तरह input और output को types से define करने वाली संरचना है
Apollo ने fragment masking जोड़कर इसे थोड़ा बेहतर बनाया है, लेकिन अब भी Relay-केंद्रित सोच महत्वपूर्ण है
और backend उसे एक single SQL query में बदलकर संभालता है
resolver का उपयोग सिर्फ उन data के लिए अपवादस्वरूप होना चाहिए जिन्हें DB से सीधे नहीं लाया जा सकता
पहले जब मैं एक टीम lead कर रहा था, तो FE GraphQL चाहता था इसलिए हमने इसे अपनाया
नतीजतन हर page के लिए एक विशाल query से सारा data लाया गया, और बदलाव होने पर पूरा JSON blob फिर से भेजा गया
app चल तो रही थी, लेकिन आखिर में company pivot कर गई और वह code गायब हो गया
वास्तव में बहुत से GraphQL projects शायद ऐसे ही सिर्फ औपचारिक implementation बनकर रह जाते हैं
GraphQL में authentication (auth) flow सबसे बड़ी मुश्किलों में से एक है
क्योंकि resolver अलग-अलग contexts में call हो सकते हैं, इसलिए हर case को ध्यान में रखना पड़ता है
complexity और mental overhead इतने बढ़ जाते हैं कि आखिरकार fields को lock करना पड़ता है
मैंने खुद graphql-autharoo बनाया, लेकिन वह भी पर्याप्त नहीं था
ज़्यादातर features GraphQL के बिना भी कहीं ज़्यादा सरल तरीके से implement किए जा सकते हैं
हर GraphQL resource पर fine-grained permissions जोड़नी पड़ती हैं, इसलिए जब तक पूरा resource update न हो जाए, query काम नहीं करती
यह इतना बोझिल है कि “इसे REST में फिर से बनाना बेहतर है” जैसी बात निकलती है
मेरा मानना है कि खुद composition करने के बजाय कोई mature server framework इस्तेमाल करना बेहतर है
GraphQL ऊपर से अच्छा दिखता है, लेकिन असल में समय के साथ maintain करना मुश्किल होने वाली technology है
कई दूसरी technologies की तरह, यह भी आखिरकार वही सबक देती है कि पहिया आखिर पहिया ही होता है
GraphQL का फायदा यह है कि schema में सिर्फ fields जोड़ देने भर से सभी clients उन्हें तुरंत query कर सकते हैं
“यह field भी जोड़ दीजिए” जैसी FE requests गायब हो जाती हैं, जिससे collaboration आसान हो जाता है
साथ ही schema snapshot बनाकर integration tests में changes detect करना भी आसान होता है
मुझे यह REST से ज़्यादा consistent लगा, हालांकि यह व्यक्तिगत अनुभव है
A से E तक chain में requests की जा सकती हैं, इसलिए performance गिरने या frontend-data structure coupling बढ़ने का खतरा रहता है
React भी अब framework-based SSR और server components को default दिशा की तरह ले रहा है
आखिरकार चीज़ें TypeScript के client और server को एकीकृत करने की ओर बढ़ रही हैं
मैं जानना चाहता हूँ कि GraphQL DB load या inefficient queries की समस्या को कैसे रोकता है
क्या malicious queries internal state को explode नहीं कर सकतीं?
REST बहुत उबाऊ लगने लगा था, इसलिए GraphQL आज़मा रहा हूँ
यह बात पसंद है कि server और client request-response पर compile time पर सहमत हो सकते हैं
अच्छा होता अगर blogs सिर्फ “यह खराब है” कहने के बजाय alternative technologies भी सुझाते
दोनों technologies client-server contract problem को अच्छी तरह हल करती हैं
फायदे और नुकसान दोनों होंगे, लेकिन schema level पर data और access control को design करना, और हर बार कुछ जोड़ते समय Rest API में अलग से जोड़ते जाना, फिर बाद में सब कुछ return करने से यह बेहतर लगता है। कमियां साफ़ हैं, लेकिन फायदे भी उतने ही साफ़ हैं haha