PRODसंप्रभु यूरोपीय BaaS मंचडैशबोर्ड खोलें →

इंजीनियरिंग · 10 मिनट पढ़ा

RLS बनाम प्रति प्रोजेक्ट एक समर्पित डेटाबेस

Affane Daylami · Fondateur · 27 जुलाई 2026

ब्लॉग पर वापस जाएँ

"आरएलएस मल्टी-टेनेंट पोस्टग्रेज" खोजें और आपको लगभग हर जगह एक ही स्कीम मिलेगी: एक साझा डेटाबेस, एक टेनेंट_आईडीकॉलम, एक नीति जो पंक्तियों को फ़िल्टर करती है। यह वह मॉडल नहीं है जिसका उपयोग ऑराबेस अपनी परियोजनाओं को एक दूसरे से अलग करने के लिए करता है। प्रत्येक प्रोजेक्ट को अपना स्वयं का पोस्टग्रेज 16 डेटाबेस प्राप्त होता है, जिसे कभी भी किसी अन्य क्लाइंट के साथ साझा नहीं किया जाता है - आरएलएस वहां रहता है, लेकिन किसी अन्य मंजिल पर: आपके डेटाबेस में, आपके अपने उपयोगकर्ताओं के लिए।

यह अंग्रेजी पाठ फ़्रेंच मूल से स्वचालित रूप से उत्पन्न हुआ था और अभी तक इसकी समीक्षा नहीं की गई है।
यह पृष्ठ स्वचालित रूप से अनुवादित किया गया था. अंग्रेजी संस्करण प्रामाणिक है.

इस विषय पर पहले से ही प्रकाशित लगभग सभी सामग्री में "आरएलएस" और "मल्टी-टेनेंट" एक साथ पाए जाते हैं - कई SaaS आर्किटेक्चर के लिए एक वैध विकल्प, लेकिन जो अपने स्वयं के ग्राहकों को एक दूसरे से अलग करने के लिए ऑराबेस की पसंद नहीं है। यह पोस्ट वास्तविक प्रावधान इंजन और वास्तव में लागू की गई आरएलएस नीतियों के बीच अंतर बताती है, न कि कोई सरल विपणन विवरण। ऑराबेस का प्रबंधित पोस्टग्रेज इंजन अलगाव से परे क्या कवर करता है, इसके अवलोकन के लिए, डेटाबेसदस्तावेज़ देखें।

अनिवार्य है

  • परियोजनाओं के बीच, ऑराबेस को समर्पित पोस्टग्रेज बेस द्वारा अलग किया जाता है, अकेले आरएलएस द्वारा कभी नहीं - प्रत्येक प्रोजेक्ट का अपना भौतिक आधार होता है, एक समर्पित सीएनपीजी क्लस्टर (कंपनी स्तर) पर या अपने स्वयं के संगठन (फ्री/प्रो/टीम) के सीएनपीजी क्लस्टर पर, कभी भी किसी अन्य संगठन के साथ साझा नहीं किया जाता है।
  • आरएलएस (auth.uid(), auth.role(), auth.jwt()) आपके आधार के अंदर सक्रिय और अनुशंसित रहता है, ताकि आपके अपने उपयोगकर्ताओं को अलग किया जा सके - सुपाबेस के समान परंपरा।
  • service_role और प्रोजेक्ट-आधारित प्रशासन भूमिकाएँ डिज़ाइन द्वारा RLS को बायपास करती हैं (BYPASSRLS): सर्वर संचालन के लिए एक अनुमानित वास्तुशिल्प विकल्प, कोई दोष नहीं।
  • इस रिपॉजिटरी में पहले से ही सुधारा गया एक प्रतिगमन - पुराने साझा स्कीमा पर त्रुटि के कारण दिए गए PUBLIC अधिकार - ठोस रूप से दर्शाते हैं कि आधार स्तर पर एक सीमा विशुद्ध रूप से अनुप्रयोग सीमा से बेहतर प्रतिरोध क्यों करती है।
#
डिफ़ॉल्ट मॉडल

वह शॉर्टकट जो अधिकांश मल्टी-टेनेंट आरएलएस गाइड अपनाते हैं

बहु-किरायेदार पोस्टग्रेज़ के लिए सबसे प्रलेखित पैटर्न में तीन पंक्तियाँ होती हैं: एक एकल आधार, प्रत्येक तालिका पर एक tenant_id कॉलम, एक RLS नीति जो इस कॉलम की तुलना JWT से निकाले गए मान से करती है। यह किफायती है - कनेक्शन का एक पूल, एक आरेख, चलाने के लिए एक एकल उदाहरण - और यह अच्छी तरह से काम करता है जब किरायेदार कई, छोटे और कम व्यक्तिगत हिस्सेदारी वाले होते हैं।

समझौता वास्तविक है: दो ग्राहकों के बीच की सीमा एक SQL अभिव्यक्ति बन जाती है, जिसका मूल्यांकन तालिका दर तालिका किया जाता है। नई टेबल पर भूली गई नीति, सुपरयूजर भूमिका के साथ चलने वाला कनेक्शन, डिबग स्क्रिप्ट को लाइव लॉन्च किया गया - इनमें से प्रत्येक घटना, संचालन में कितनी भी छोटी हो, एक ही समय में सभी किरायेदारों की पंक्तियों को चुपचाप उजागर कर सकती है। सुरक्षा सीमा और तकनीकी सीमा (आधार) बिल्कुल एक ही चीज़ हैं।

जानकारी

यह अपने आप में कोई बुरा विकल्प नहीं है - यह कई उत्पादों के लिए सही समझौता है। इस पोस्ट का मुद्दा कहीं और है: यह वह समझौता नहीं है जो ऑराबेस ने अपने ग्राहकों (संपूर्ण परियोजनाओं, संभावित रूप से विभिन्न अनुपालन आवश्यकताओं के साथ) को एक दूसरे से अलग करने के लिए किया है।

#
कोड में

दो आर्किटेक्चर, कभी भी परियोजनाओं के बीच साझा आधार नहीं

प्रोविजनर के हालिया समेकन (कोड में "टास्क 12" के रूप में चिह्नित) के बाद से, ऑराबेस में एक सक्रिय पोस्टग्रेज परियोजना बिल्कुल दो आर्किटेक्चर के अंतर्गत आती है - कई परियोजनाओं के बीच वास्तव में साझा किए गए आधार वाले पुराने मॉडल को प्रोविजनिंग पथ से हटा दिया गया है।

provisioning/instances.rsrust
pub enum ProjectInstanceKind {
    /// सीएनपीजी क्लस्टर केवल इसी परियोजना (कंपनी स्तर) को समर्पित है।
    FullyDedicated,

    /// परियोजना संगठन के सीएनपीजी क्लस्टर पर डेटाबेस -
    /// समान संगठन की अन्य परियोजनाओं के साथ साझा किया गया,
    /// कभी भी किसी तीसरे पक्ष के संगठन के साथ नहीं।
    SharedClusterDedicated,
}

प्रोजेक्ट स्तर तय करता है कि दोनों में से कौन सा लागू होता है - और यह कोड है जो निर्णय लेता है, डैशबोर्ड में चेक किया गया बॉक्स नहीं:

provisioning/rules.rsrust
fn should_provision_dedicated(engine: &str, db_url_encrypted: &Option<String>, plan: &str) -> bool {
    matches!(engine, "postgres" | "postgresql")
        && plan == "enterprise"
        && !non_empty(db_url_encrypted)
}

// shud_route_to_fleet(): कोई भी गैर-कंपनी स्तर (निःशुल्क/समर्थक/टीम)
// आपके अपने संगठन के सीएनपीजी क्लस्टर का मार्ग, कभी भी एक नहीं
// दूसरे से - माइग्रेशन 073, 2 आर्किटेक्चर में समेकन देखें।
DIMENSIONSपूर्णतः समर्पित (कंपनी)शेयर्डक्लस्टरसमर्पित (निःशुल्क/समर्थक/टीम)
सीएनपीजी क्लस्टरइस एक परियोजना के लिए समर्पितसाझा, लेकिन दो संगठनों के बीच कभी नहीं
डेटाबेस पोस्टग्रेज करता हैऐप, केवल उस पर प्रोजेक्ट करेंproject_<uuid>, क्लस्टर पर प्रति प्रोजेक्ट एक
पोस्टग्रेएसक्यूएल लॉगिनक्लस्टर पर एक एकल परियोजना: क्रॉस-सदस्यता का कोई जोखिम नहींप्रति-प्रोजेक्ट (F-013) लॉगिन करें, इसकी एकमात्र भूमिकाओं के सदस्य किरायेदार_<uuid>

दोनों आर्किटेक्चर पर, आधार या क्लस्टर कभी भी दो अलग-अलग संगठनों को होस्ट नहीं करता है - इसलिए सवाल यह नहीं है कि "क्या आपका डेटा अलग है" बल्कि "क्या आपके प्रोजेक्ट ने CloudNativePG की गणना स्वयं की है, या क्या यह इसे उसी संगठन में अन्य परियोजनाओं के साथ साझा करता है।"

दो आर्किटेक्चर का यह समेकन हालिया है: कोड में पहले दो अतिरिक्त पथ थे - एक "साझा मास्टर" जहां कई परियोजनाएं एक ही डेटाबेस में सह-अस्तित्व में थीं, केवल आरेख द्वारा अलग की गईं, और एक postgrest_dedicated_shared_dbसंस्करण। एक समर्पित माइग्रेशन ने उन्हें हटा दिया और projects तालिका की बाधा को केवल दो शेष मानों तक कड़ा कर दिया, ठीक इसलिए क्योंकि साझा स्कीमा मॉडल नीचे वर्णित बग का स्रोत था।

#
सुरक्षा सीमा

क्यों एक समर्पित आधार ग्राहकों के बीच साझा किए गए ईपीआईआरबी को मात देता है

एक अलग पोस्टग्रेज़ डेटाबेस एक कनेक्शन-स्तरीय सीमा है, पंक्ति-स्तरीय सीमा नहीं। प्रोजेक्ट ए के डेटाबेस से जुड़ी एक एप्लिकेशन भूमिका प्रोजेक्ट बी की तालिकाओं को क्वेरी नहीं कर सकती है - इसमें कोई सत्र खुला नहीं है। यह संपत्ति तब भी कायम रहती है, जब कोई आरएलएस नीति खराब तरीके से लिखी गई हो, तालिका से गायब हो, या उच्च भूमिका से उपेक्षित हो: सबसे खराब स्थिति एकल डेटाबेस तक ही सीमित रहती है।

इस जमा में एक वास्तविक बग का निशान भी है जो विपरीत जोखिम को दर्शाता है। पुराने साझा स्कीमा मॉडल के तहत (अब वापस ले लिया गया है), provision_postgres_schema ने गलती से प्रत्येक प्रोजेक्ट स्कीमा के लिए GRANT ALL ... TO PUBLIC अधिकार प्रदान कर दिए - PUBLIC ने सदस्यता शर्तों के बिना डेटाबेस में सभी भूमिकाओं पर लागू होते हुए, प्रति प्रोजेक्ट अलग किया गया एक लॉगिन दूसरे के स्कीमा में पढ़ और लिख सकता है। एक सुधारात्मक माइग्रेशन (066) ने इन अधिकारों को मौजूदा अधिकारों से हटा दिया।

सबक सीखा

पैच ने रिसाव को रोकने के लिए एक और आरएलएस नीति नहीं जोड़ी - इसने डेटाबेस साझा करने वाली दो परियोजनाओं की संभावना को हटा दिया। दो वर्तमान आर्किटेक्चर पर, provisioning.rs की एक टिप्पणी इसे काले और सफेद रंग में दस्तावेज़ित करती है: "प्रत्येक प्रोजेक्ट के पास पहले से ही अपना स्वयं का भौतिक पोस्टग्रेज डेटाबेस है"। प्रत्येक नीति के हमेशा सही ढंग से लिखे जाने पर निर्भर रहने के बजाय, आधार-स्तरीय सीमा ऐसे बगों की एक पूरी श्रेणी को आसानी से पहुंच योग्य नहीं बनाती है।

23 अगस्त, 2026 का एक पैच उसी दिशा में जाता है: प्रावधानकर्ता द्वारा बिना शर्त रखे गए REVOKE ALL ON SCHEMA public को टोपोलॉजी पर सशर्त बनाया गया था, क्योंकि यह केवल पुराने साझा डेटाबेस मॉडल पर वास्तविक अलगाव प्रदान करता था - दो मौजूदा आर्किटेक्चर पर, इसने SQL डंप के आयात को लाभ के बिना अवरुद्ध कर दिया जो स्पष्ट रूप से public.<table>को संदर्भित करता है।

#
व्यवहार में आर.एल.एस

EPIRB वहीं रहता है - आपके डेटाबेस में, आपके उपयोगकर्ताओं के लिए

उपरोक्त में से कोई भी ईपीआईआरबी को बेकार नहीं बनाता है - यह सिर्फ फर्श बदलता है। एक बार आपके प्रोजेक्ट डेटाबेस में, Aurabase बिल्कुल Supabaseद्वारा अपनाए गए PostgREST सम्मेलन को उजागर करता है: तीन SQL फ़ंक्शन जो request.jwt.claimsमें गेटवे द्वारा निर्धारित JWT दावों को पढ़ते हैं।

libs/aura-migrations/golden/auth_global.sqlsql
create function auth.uid() returns uuid
    language sql stable security definer
    set search_path to 'pg_catalog', 'pg_temp'
    as $$
    select nullif(nullif(current_setting('request.jwt.claims', true), '')::json->>'sub', '')::uuid
$$;

इन सहायकों का उपयोग ऑराबेस की वास्तविक नीतियों में ही किया जाता है - न कि केवल आपके लिए प्रलेखित। यहां वह नीति है जो storage_objectsकी सुरक्षा करती है, क्योंकि इसे रिपॉजिटरी में रखा गया है (पढ़ने के लिए कई पंक्तियों में पुन: स्वरूपित किया गया है):

libs/aura-migrations/golden/storage.sqlsql
alter table storage_objects enable row level security;

create policy storage_objects_select on storage_objects
  for select using (
    (owner_id = auth.uid())
    or (
      exists (
        select 1 from storage_buckets b
        where (b.name = storage_objects.bucket_name and b.public)
      )
    )
  );

आपके स्वयं के project_<uuid>स्कीमा में, जो आपके एप्लिकेशन तालिकाओं को ले जाता है, ऑराबेस जानबूझकर आपकी ओर से कोई नीति नहीं रखता है - कोड इसे "सुपाबेस मॉडल" के रूप में दस्तावेजित करता है: आपकी तालिकाओं का आरएलएस आपकी ज़िम्मेदारी बनी हुई है, समान कार्यों, समान वाक्यविन्यास के साथ।

#
BYPASSRLS मान लिया गया

service_role RLS को बायपास करता है - डिज़ाइन द्वारा, दुर्घटना से नहीं

पोस्टग्रेज़ मूल रूप से एक भूमिका विशेषता, BYPASSRLSप्रदान करता है, जो सभी नीतियों को अनदेखा करता है। ऑराबेस स्वेच्छा से भूमिकाओं के दो परिवारों पर इसका उपयोग करता है: aura_service_role (सर्वर भूमिका, ब्राउज़र पक्ष पर कभी भी उजागर नहीं) और प्रत्येक प्रोजेक्ट के लिए विशिष्ट प्रशासन भूमिका, जिसका उपयोग ALTER SCHEMA ... OWNER TOजैसे DDL संचालन के दौरान किया जाता है।

provisioning/roles.sqlsql
create role aura_service_role nologin bypassrls;
-- सर्वर भूमिका: ब्राउज़र पक्ष पर कभी प्रदर्शित नहीं, कभी सदस्य नहीं
-- किसी अन्य प्रोजेक्ट से भूमिकाएँ।

वह भूमिका जो आपके अनुरोधों को पूरा करती है anon/authenticated - tenant_<uuid> - में कोई BYPASSRLSनहीं है: आरएलएस बिना किसी अपवाद के सामान्य रूप से इस पर लागू होता है। एक बोनस के रूप में, प्रत्येक परियोजना के लिए विशिष्ट सिस्टम आरेख (_auth, _storage, _platform) को नीति के बिना एक सक्रिय आरएलएस प्राप्त होता है - इसलिए किसी भी गैर-बायपास भूमिका के लिए डिफ़ॉल्ट रूप से पूर्ण इनकार, एक दिन गलती से एप्लिकेशन पथ तक पहुंचने की स्थिति में गहराई से बचाव।

जानकारी

उन्नत सर्वर भूमिका के साथ आरएलएस को बायपास करना ऑराबेस के लिए अद्वितीय नहीं है - यह सुपाबेस पक्ष पर service_role जैसा ही निर्माण है। बात BYPASSRLSसे बचने की नहीं है, बात यह है कि इसे कभी भी क्लाइंट से सुलभ भूमिका न दी जाए, और इसे एक ही प्रोजेक्ट तक सीमित रखा जाए।

यह सर्वर भूमिका एक व्यापक स्थिति का हिस्सा है - पूर्वनिर्धारित भूमिकाएँ, कस्टम RBAC, ऑडिट लॉग - सुरक्षा और RBACपृष्ठ पर विस्तृत है।

#
गहराई में बचाव

साझा क्लस्टर पर, डेटाबेस सारा काम अकेले नहीं करता है

SharedClusterDedicatedस्तर पर, एक ही संगठन की कई परियोजनाएं एक ही सीएनपीजी क्लस्टर पर सह-अस्तित्व में हैं। भौतिक डेटाबेस पहले से ही परियोजनाओं को एक-दूसरे से अलग करता है, लेकिन PostgreSQL भूमिकाएँ - वे - क्लस्टर के लिए वैश्विक ऑब्जेक्ट हैं, डेटाबेस के लिए नहीं। इसलिए ऑराबेस एक परत जोड़ता है: प्रति प्रोजेक्ट एक अलग PostgreSQL लॉगिन।

libs/aura-core/src/lib.rsrust
pub fn project_authenticator_role(project_id: &str) -> String {
    format!("project_{}_authenticator", project_id.replace('-', '_'))
}

// डिफ़ॉल्ट रूप से सक्रिय (F013_PER_PROJECT_AUTHENTICATOR), निष्क्रिय करने योग्य
// स्पष्ट रूप से एक आपातकालीन पलायन के रूप में।

प्रत्येक प्रोजेक्ट अपने स्वयं के लॉगिन से जुड़ता है, केवल अपनी tenant_<uuid> / tenant_<uuid>_admin भूमिकाओं का सदस्य होता है - कभी भी उसी क्लस्टर में किसी अन्य प्रोजेक्ट का नहीं। डेटाबेस पहले से ही डेटा को अलग कर देता है; यह लॉगिन प्रति प्रोजेक्ट उस पहचान को भी अलग कर देता है जो उससे जुड़ती है, ताकि किसी प्रोजेक्ट पर कोई घटना उसके लॉगिन को किसी अन्य को विरासत में लेने के लिए कोई सदस्यता न दे।

#
आपकी वास्तुकला के लिए

अकेले आरएलएस या समर्पित आधार: अपने स्वयं के सास के लिए निर्णय कैसे लें

ऑराबेस का चुनाव एक सार्वभौमिक नियम नहीं है - यह एक विशिष्ट मामले के लिए एक समझौता है: ग्राहकों को एक दूसरे से अलग करना, संभावित रूप से विभिन्न अनुपालन आवश्यकताओं के साथ, एक ऐसे मंच पर जिसे वे नियंत्रित नहीं करते हैं। यदि आप अपना स्वयं का SaaS बना रहे हैं, तो आपके लिए भी यही प्रश्न एक अलग पैमाने पर उठता है।

  • साझा आधार में tenant_id के साथ आरएलएस - तब प्रासंगिक होता है जब आपके किरायेदार असंख्य होते हैं, व्यक्तिगत रूप से कम हिस्सेदारी वाले होते हैं, और प्रति किरायेदार आधार की लागत अनुपातहीन होगी। बिना किसी अपवाद के, प्रत्येक तालिका पर pg_proveके साथ प्रत्येक नीति का परीक्षण करें।
  • समर्पित आधार या आरेख - प्रासंगिक जब भी किसी किरायेदार के पास अपना अनुपालन मुद्दा (स्वास्थ्य, मानव संसाधन, सार्वजनिक क्षेत्र) होता है, एक मात्रा जो प्रदर्शन अलगाव को उचित ठहराती है, या दो विशिष्ट ग्राहकों के बीच रिसाव की लागत अतिरिक्त बुनियादी ढांचे की लागत से असंगत होगी।

ऑराबेस मूल्य निर्धारण स्तर अपने स्वयं के ग्राहकों पर इसी मध्यस्थता को लागू करता है: डिफ़ॉल्ट रूप से संगठन द्वारा साझा आधार, समर्पित क्लस्टर जब परियोजना की चुनौती इसे उचित ठहराती है। आपके अपने डेटाबेस के अंदर आरएलएस पैटर्न के लिए - स्वामित्व, संगठन द्वारा बहु-किरायेदार, भूमिका पदानुक्रम - उत्पादन में आरएलएस गाइड pgTAPपरीक्षणों के साथ तीन मामलों का विवरण देता है। और यदि आपके आरेख पर ऑटो-जनरेटेड एपीआई आपको REST से अधिक रुचिकर लगती है, तो pg_graphql बनाम हसुरा और पोस्टग्राफ़ाइल पर तुलना ऑराबेस द्वारा उजागर की गई पोस्टग्रेज सतह के दूसरे आधे हिस्से को कवर करती है।

#
अक्सर पूछे जाने वाले प्रश्नों

पूछे जाने वाले प्रश्न

क्या एकल पोस्टग्रेज़ डेटाबेस में किरायेदारों को अलग करने के लिए अकेले आरएलएस पर्याप्त है?+
तकनीकी रूप से हाँ, यदि प्रत्येक तालिका सही नीति अपनाती है और कोई भी कनेक्शन गैर-बायपास भूमिका से बच नहीं पाता है। यह बिल्कुल परिचालन जोखिम है जिसे ऑराबेस ने विभिन्न परियोजनाओं के बीच नहीं लेने का फैसला किया - प्रत्येक नीति त्रुटि एक ही आधार तक सीमित रहेगी। एक ही प्रोजेक्ट के भीतर, आपके अपने किरायेदारों के लिए, आरएलएस + किरायेदार_आईडी एक वैध और व्यापक रूप से इस्तेमाल किया जाने वाला विकल्प बना हुआ है।
मुफ़्त परियोजनाओं में एंटरप्राइज़ स्तर की तरह एक समर्पित पोस्टग्रेज़ क्लस्टर क्यों नहीं है?+
प्रति प्रोजेक्ट एक समर्पित क्लाउडनेटिवपीजी क्लस्टर, जिसमें मुफ्त प्रोजेक्ट भी शामिल हैं, उनमें से अधिकांश के वास्तविक उपयोग के संबंध के बिना आरक्षित गणना को कई गुना बढ़ा देगा। इसके बजाय ऑराबेस प्रत्येक गैर-उद्यम परियोजना को अपने स्वयं के संगठन के सीएनपीजी क्लस्टर पर अपना स्वयं का भौतिक पोस्टग्रेज डेटाबेस देता है - जिसे कभी भी किसी अन्य संगठन के साथ साझा नहीं किया जाता है - एक दूसरे के लिए अज्ञात कई ग्राहकों के बीच एक सामान्य डेटाबेस में एक स्कीमा के बजाय।
तकनीकी रूप से auth.uid() को कैसे पता चलता है कि मैं कौन हूं?+
ऑराबेस गेटवे आपके JWT को सत्यापित करता है और फिर लेनदेन की अवधि के लिए अपने दावों को Postgres सत्र पैरामीटर request.jwt.claims में रखता है। auth.uid() इस JSON से उप फ़ील्ड को निकालने और इसे uuid में डालने के अलावा और कुछ नहीं करता है - बिना किसी दावे के (गुमनाम अनुरोध, या गेटवे के बाहर सीधा कनेक्शन), current_setting() NULL लौटाता है और auth.uid() इसलिए NULL लौटाता है, जो (owner_id = auth.uid()) का उपयोग करके पॉलिसी तक पहुंच बंद कर देता है।

तैनाती के लिए तैयार हैं?

पाँच मिनट में आपका बैकएंड।

किसी क्रेडिट कार्ड की आवश्यकता नहीं · 500 एमबी निःशुल्क · 50,000 एमएयू