← ब्लॉग

Vercel पर Supabase का 'max clients reached in session mode', और वह फ़िक्स जिसने इसे और बिगाड़ा

20 सितंबर 2026 · 7 मिनट में पढ़ें

एरर है (EMAXCONNSESSION) max clients reached in session mode - max clients are limited to pool_size: 15। हमारा API यह लौटाने लगा, जबकि मार्केटिंग साइट बिल्कुल ठीक चलती रही, क्योंकि मार्केटिंग साइट Postgres को छूती ही नहीं। ठीक इसी वजह से इस तरह की गड़बड़ी पर किसी का ध्यान नहीं जाता। जो हिस्से ठीक दिखते हैं, उन्हें डेटाबेस की ज़रूरत ही नहीं होती।

यहाँ बताया है कि एरर का मतलब क्या है, इसे ठीक करते हुए हमने कौन सी दो गलतियाँ कीं, और वह कनेक्शन स्ट्रिंग जो Vercel से सच में चलती है।

दो पूलर, दो पोर्ट

सर्वरलेस session mode को ख़त्म क्यों कर देता है

हर गर्म फ़ंक्शन इंस्टेंस अपना एक छोटा पूल रखता है। हमारे में तीन कनेक्शन थे। Session mode वाला पूल इंस्टेंस गर्म रहने तक कनेक्शन कभी वापस नहीं देता। पाँच गर्म इंस्टेंस मतलब पंद्रह कनेक्शन, यानी सीमा। कहीं से भी आई छठी रिक्वेस्ट फ़ेल हो जाती है।

हर कुछ सेकंड में तीन एंडपॉइंट पोल करने वाला फ़्लीट डेमन इंस्टेंस को चौबीसों घंटे गर्म रखता था। इसमें कुछ भी असामान्य नहीं है। यह बस वह गणित है जिसमें session mode हार जाता है।

पहली गलती: पहले गलत लेयर ठीक करना

इमरजेंसी फ़िक्स था हर इंस्टेंस पर max: 1 और बीस सेकंड का idle timeout, अब भी session mode पर। यह चल गया। जो इंस्टेंस शांत हुए, उन्होंने अपनी जगह लौटा दी, और API कुछ ही मिनटों में ठीक हो गया। फिर हमने कनेक्शन स्ट्रिंग transaction mode पर कर दी, जो सही कदम था। हमने max: 1 वैसे ही छोड़ दिया, जो सही नहीं था।

दूसरी गलती: transaction mode पर एक का पूल

Transaction mode पर हर इंस्टेंस में एक ही कनेक्शन होने से उस इंस्टेंस की हर क्वेरी एक ही पाइप के पीछे लाइन में लग जाती है। डेमन की पोलिंग उसके पीछे जमा हो गई। रिक्वेस्ट अपनी बीस सेकंड की डेडलाइन पार करने लगीं, और लक्षण 500 से बदलकर अटकने में बदल गया। मार्केटिंग साइट अब भी तेज़ थी। API ने जवाब देना ही बंद कर दिया।

Transaction mode हर ट्रांज़ैक्शन के बाद कनेक्शन लौटा देता है, इसलिए उसे सामान्य साइज़ का पूल चाहिए। हमने आठ रखा, और टाइमआउट रुक गए।

इसे आते हुए कैसे देखें

पूलर मना करने तक कुछ नहीं बताता। पूछें, तो Postgres ख़ुद बता देगा।

select application_name, state, count(*)
from pg_stat_activity
where datname = 'postgres'
group by 1, 2
order by 3 desc;

ऐप पर सामान्य लोड के समय इसे session कनेक्शन पर चलाएँ। अगर गिनती धीरे धीरे सीमा की ओर बढ़ रही है और ज़्यादातर पंक्तियाँ idle हैं, तो आप एरर से बस एक व्यस्त मिनट दूर हैं। Transaction mode पर यही क्वेरी दिखाती है कि कनेक्शन जमा होने की जगह रीसायकल हो रहे हैं।

वह कनेक्शन स्ट्रिंग जो सच में चलती है

postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres
  • होस्ट पूलर है, db.<ref>.supabase.co नहीं। Supabase डैशबोर्ड transaction pooler वाले हेडिंग के नीचे डायरेक्ट होस्ट दिखा सकता है। फिर भी वह डायरेक्ट होस्ट ही है।
  • पूलर पर यूज़रनेम postgres.<project-ref> है। सिर्फ़ postgres केवल डायरेक्ट होस्ट पर चलता है।
  • डायरेक्ट होस्ट सिर्फ़ IPv6 है, जब तक आप IPv4 ऐड-ऑन न ख़रीदें। उसका AAAA रिकॉर्ड है, A रिकॉर्ड नहीं। Vercel फ़ंक्शन उस तक नहीं पहुँच सकते, और वहाँ पोर्ट 6543 वैसे भी खुला नहीं है।
  • postgres.js के लिए क्वेरी स्ट्रिंग की ज़रूरत नहीं। prepare: false सेट करें। ?pgbouncer=true फ़्लैग Prisma का तरीका है।
  • माइग्रेशन 5432 पर रखें। Drizzle जैसे टूल session कनेक्शन चाहते हैं। डिप्लॉय हुए ऐप को 6543 पर और लोकल माइग्रेशन env को 5432 पर रखें।
$ dig +short A    db.<project-ref>.supabase.co     # (nothing)
$ dig +short AAAA db.<project-ref>.supabase.co     # 2600:1f18:...
$ nc -z aws-0-us-east-1.pooler.supabase.com 6543   # succeeded

साइज़, एक टेबल में

आख़िरी बात जानने लायक है। जब यह सब हो रहा था, तब API तक न पहुँच पाने वाले डेमन ने मान लिया कि उसकी हर मशीन बंद है। वह उनका पावर साइकिल करने की तैयारी में था। वह कहानी कैसे एक डेटाबेस कनेक्शन लिमिट ने लगभग मेरे ग्राहकों के Mac रीबूट कर दिए में है।

सवाल

Vercel ऐप को Supabase का कौन सा पोर्ट इस्तेमाल करना चाहिए?
6543, यानी transaction mode वाला पूलर। 5432 पर session mode हर क्लाइंट के लिए एक सर्वर कनेक्शन रखता है और प्रोजेक्ट को 15 तक सीमित करता है। सर्वरलेस इसे जल्दी ख़त्म कर देता है।
Vercel से db.<project-ref>.supabase.co कनेक्ट क्यों नहीं होता?
डायरेक्ट होस्ट का सिर्फ़ IPv6 पता होता है, जब तक आप IPv4 ऐड-ऑन के पैसे न दें। Vercel फ़ंक्शन IPv6 पर उस तक नहीं पहुँचते। पूलर होस्ट aws-0-<region>.pooler.supabase.com इस्तेमाल करें।
पूलर को कौन सा यूज़रनेम चाहिए?
postgres.<project-ref>, यानी आख़िर में प्रोजेक्ट ref जोड़कर। सिर्फ़ postgres केवल डायरेक्ट होस्ट पर चलता है।
क्या कनेक्शन स्ट्रिंग में ?pgbouncer=true चाहिए?
Prisma के लिए हाँ। postgres.js के लिए इसकी जगह क्लाइंट ऑप्शन में prepare: false सेट करें। Transaction mode, prepared statements सपोर्ट नहीं करता।
हर मोड में पूल साइज़ कितना रखें?
Session mode: हर इंस्टेंस पर एक या दो, छोटे idle timeout के साथ, क्योंकि सीमा पंद्रह है। Transaction mode: सामान्य पूल, पाँच से दस, क्योंकि हर ट्रांज़ैक्शन के बाद कनेक्शन लौट आते हैं।

अपना हिसाब खुद लगाएँ: कैलकुलेटर देखें, या एक runner लीज़ करें।