GMI Software
Główne obszary
AI & Automatyzacje
Od procesu i business case do produkcji
Aplikacje mobilne
iOS, Android, React Native
E-commerce headless & B2B
Sklepy, platformy sprzedaży, integracje ERP/PIM
Usługi komplementarne
AI-gen developmentAnalityka e-commerce mobileProduct Discovery & DesignBackend, API & IntegracjeUtrzymanie & AudytyProces DDT
Nie wiesz co wybrać? Zamów konsultację
Nasze projekty
Case studies i referencje
Biblioteka aplikacji
Przykłady zastosowań
MobileNasza specjalizacja
React Native
E-commerceNasza specjalizacja
Usługa: e-commerce & B2BZaawansowany e-commerceMedusaJS
Frontend & QA
Next.jsReactTypeScriptPlaywrightMaestro
Backend, Bazy & Cloud
Node.jsNestJSPostgreSQLDockerAWS
Innowacje w E-commerce
Konfiguratory 3D (BabylonJS)Automatyzacje i Agenci AIRAG i bazy wiedzySoftware house AI-nativeZobacz wszystkie usługi AI
Zobacz wszystkie technologie
O nas
Nasza historia i wartości
Kariera
Dołącz do zespołu
Kontakt
Skontaktuj się z nami
Skontaktuj się
Sprint AI dla biznesu
Usługi
Aplikacje mobilneE-commerce headless & B2BWszystkie usługi
Projekty i wyniki
Technologie
Next.jsNode.jsAWSCały stack technologiczny
Poznaj GMISkontaktuj się
Wróć do bloga
Technologie
Zaktualizowano: 11 lipca 2026· Pierwsza publikacja: 14 marca 2026
18 min czytania

Jak zabezpieczyć dane wielu firm w jednej aplikacji z PostgreSQL?

Mikołaj Lehman, CEO i założyciel GMI Software
Mikołaj Lehman
CEO i założyciel GMI Software

Mikołaj Lehman jest CEO i założycielem GMI Software. Na blogu opisuje decyzje związane z aplikacjami mobilnymi, e-commerce oraz realizacją produktów cyfrowych.

  • Aplikacje mobilne i React Native
  • Headless i e-commerce B2B
  • MedusaJS
  • Realizacja produktów cyfrowych

Krótka odpowiedź: kontrola dostępu do pojedynczych wierszy w PostgreSQL ma sens w aplikacji abonamentowej, w której wielu klientów współdzieli tabele, ale każdy wiersz musi być filtrowany przez kontekst firmy ustawiany przez aplikację. Nie zastępuje autoryzacji w NestJS ani testów, ale dodaje barierę w silniku bazy, która chroni przed zapomnianym `WHERE tenant_id = ...`, błędnym zapytaniem z warstwy pracy z bazą i częścią pomyłek w narzędziach administracyjnych.

Najpierw problem: jeden system dla wielu firm obniża koszt, ale koncentruje ryzyko

Aplikacja abonamentowa obsługująca wielu klientów jest kusząca, bo jedna aplikacja i jedna infrastruktura pracują dla wielu firm. Zamiast utrzymywać osobną bazę dla każdej organizacji, trzymasz dane w tych samych tabelach, zwykle z kolumną identyfikującą firmę. Koszt infrastruktury spada, migracje są prostsze, a wdrażanie funkcji jest szybsze.

Takie podejście ma jednak jedno brutalne ryzyko: wyciek danych między klientami. Jeśli klient A zobaczy faktury, użytkowników, notatki z obsługi klienta albo dokumenty klienta B, problem nie jest "bugiem". To incydent bezpieczeństwa, utrata zaufania, potencjalne konsekwencje prawne i rozmowa z największym klientem, której nikt nie chce prowadzić.

Dlatego w systemach dla klientów firmowych nie wystarczy mówić "nasza aplikacja zawsze dodaje filtr firmy". Wystarczy jeden punkt dostępu, raport, eksport CSV, zadanie w tle, widok administratora albo surowe zapytanie bez filtra. Kontrola dostępu do pojedynczych wierszy w PostgreSQL nie usuwa całego ryzyka, ale przenosi część izolacji z pamięci programisty do silnika bazy.

Wspólne tabele, osobna baza czy podejście mieszane: trzy sposoby izolacji klientów

Zanim wybierzesz polityki dostępu w bazie, musisz zdecydować, jak oddzielasz klientów. Osobna baza albo osobny schemat dla klienta daje najmocniejszą izolację i łatwiejsze odtwarzanie danych pojedynczej firmy, ale kosztuje więcej w operacjach, migracjach i automatyzacji. Wspólne tabele z separacją przez identyfikator firmy są najtańsze w skali, ale wymagają bardzo dobrych zabezpieczeń procesu.

Podejście mieszane jest kompromisem: najwięksi lub regulowani klienci dostają osobną bazę albo schemat, a mniejsze firmy działają we wspólnych tabelach. To bywa rozsądne w aplikacji dla klientów firmowych, gdzie duży klient płaci za silniejszą izolację, a mniejsi klienci potrzebują ekonomii skali.

Kontrola dostępu do wierszy dotyczy głównie wspólnych tabel. AWS Prescriptive Guidance mówi wprost, że taka ochrona jest wymagana do utrzymania izolacji klientów przy wspólnym PostgreSQL i centralizuje egzekwowanie izolacji na poziomie bazy. W praktyce oznacza to jasną mapę: aplikacja ustawia kontekst firmy, PostgreSQL egzekwuje polityki na tabelach klientów, a pamięć podręczna, wyszukiwarka i funkcje AI dostają własne zasady izolacji. To nie znaczy, że każda tabela ma wyglądać tak samo. Oznacza, że każda tabela z danymi klientów musi mieć świadomą politykę dostępu.

  • Osobna baza: najlepsza izolacja, wyższy koszt operacyjny i migracje dla każdego klienta.
  • Wspólne tabele: najlepsza ekonomia skali, najwyższy wymóg dyscypliny w izolacji danych.
  • Podejście mieszane: wspólne tabele dla większości, osobne środowisko dla dużych lub regulowanych klientów.
Grafika do artykułu: Izolacja danych w PostgreSQL dla aplikacji obsługującej wiele firm
Grafika do artykułu: Izolacja danych w PostgreSQL dla aplikacji obsługującej wiele firm

Co naprawdę robi kontrola dostępu do wierszy w PostgreSQL

Oficjalna dokumentacja PostgreSQL opisuje kontrolę dostępu do wierszy jako polityki ograniczające, które wiersze mogą być zwracane, wstawiane, aktualizowane albo usuwane. Po włączeniu tej ochrony normalny dostęp do tabeli musi być dopuszczony przez politykę. Jeśli nie ma polityki, baza domyślnie blokuje dostęp: wiersze nie są widoczne ani modyfikowalne.

Dla aplikacji obsługującej wiele firm oznacza to prostą ideę: tabela `invoices` może mieć politykę porównującą identyfikator firmy w wierszu z kontekstem aktualnej sesji. Aplikacja po uwierzytelnieniu ustawia kontekst sesji, a baza automatycznie dodaje filtr do zapytań. Nawet jeśli kod zapomni `WHERE tenant_id = ...`, normalny użytkownik nie powinien zobaczyć cudzych wierszy.

To brzmi jak magia, ale nią nie jest. Taka polityka działa dla konkretnej tabeli, roli i komendy. Właściciel tabeli oraz role z uprawnieniem omijania tych polityk mogą je ominąć. Dlatego projekt produkcyjny musi obejmować role aplikacyjne, wymuszenie polityk także dla właściciela tabeli, testy migracji oraz jasny podział między połączeniami aplikacji, administratora i utrzymania.

Wzorzec dla NestJS: kontekst firmy, transakcja i reset

Najczęstszy błąd nie leży w samej polityce bazy, tylko w ustawianiu kontekstu. Zaplecze po autoryzacji musi wiedzieć, która firma wykonuje żądanie, a potem ustawić ją w sesji PostgreSQL. W praktyce używamy kontekstu żądania w NestJS, strażników autoryzacji i warstwy klienta bazy, która nie pozwala wykonać zapytania bez ustawionego kontekstu tam, gdzie jest wymagany.

Przy puli połączeń trzeba uważać: połączenie jest używane ponownie. Dlatego kontekst firmy powinien być ustawiany na czas transakcji lub żądania i resetowany. W PostgreSQL często stosuje się `set_config('app.current_tenant', tenantId, true)` w transakcji, gdzie trzeci argument `true` ogranicza ustawienie do aktualnej transakcji.

Jeżeli używasz Prisma, Drizzle, Kysely albo surowego `pg`, zasada jest ta sama: biblioteka do zapytań nie jest granicą bezpieczeństwa. Pomaga budować zapytania, ale izolacja w PostgreSQL wymaga świadomego cyklu życia połączenia, testów i zabezpieczeń blokujących przypadkowe użycie superużytkownika albo danych dostępowych z prawem omijania polityk.

Polityki, których potrzebuje prawdziwy produkt abonamentowy

Najprostsza polityka porównująca identyfikator firmy jest tylko początkiem. Produkcyjny produkt abonamentowy potrzebuje osobnych zasad dla odczytu, tworzenia, zmiany i usuwania danych, bo widoczność wiersza i prawo do jego utworzenia lub zmiany to nie to samo. PostgreSQL pozwala używać `USING` dla dostępu i `WITH CHECK` dla danych zapisywanych.

Przykład: użytkownik może widzieć faktury swojej firmy, ale nie może zmienić identyfikatora firmy na fakturze przez dane wysłane w formularzu lub żądaniu. `WITH CHECK` powinien wymusić, że nowy lub zaktualizowany wiersz nadal należy do aktualnego klienta. Dla tabel wspólnych, jak plany subskrypcji, przełączniki funkcji albo katalog publiczny, polityka może być inna albo izolacja na poziomie wierszy nie jest właściwą granicą.

Ważne są też role. Aplikacja produkcyjna nie powinna łączyć się jako właściciel tabel ani superużytkownik. Osobne role dla działania aplikacji, migracji, raportów tylko do odczytu i awaryjnego administratora zmniejszają ryzyko, że jedna biblioteka lub skrypt wyłączy całą izolację.

Testy izolacji: nie ufaj polityce, dopóki jej nie złamiesz

Izolacja w bazie musi mieć testy negatywne. Nie wystarczy sprawdzić, że klient A widzi swoje faktury. Trzeba sprawdzić, że klient A nie widzi faktur B, nie może wstawić wiersza należącego do B, nie może przepisać swojego wiersza na B i nie dostaje danych przez relację, widok, funkcję SQL, eksport, wyszukiwarkę albo zadanie w tle.

Dobre testy tworzą dwóch klientów, dwóch użytkowników, dane o podobnym kształcie i uruchamiają scenariusze przez aplikację oraz bezpośrednio na warstwie komunikacji z bazą. Warto testować też migracje: nowa tabela z danymi klientów nie może wejść na produkcję bez polityki dostępu i indeksu po identyfikatorze firmy.

Supabase przypomina, że kontrola dostępu do wierszy jest mocna, ale trzeba ją włączyć. PostgreSQL przypomina, że jeśli ochrona jest włączona, a brak polityki, baza domyślnie blokuje dostęp. To dobre zabezpieczenie, pod warunkiem że proces przeglądu wykrywa tabele bez polityk, zanim klienci odkryją brak danych albo cudze dane po wdrożeniu.

Wydajność: izolacja w bazie nie jest darmowa, ale chaos też kosztuje

Najczęstsze pytanie dyrektora technologii brzmi: czy polityki wierszy spowolnią bazę? Odpowiedź brzmi: mogą, jeśli są złożone, odwołują się do innych tabel bez indeksów albo wymagają funkcji wykonywanych dla każdego wiersza. Prosta polityka po `tenant_id` na dobrze indeksowanych tabelach jest zwykle dużo mniej problematyczna niż ręczne filtry rozsiane po całym kodzie.

Projektuj izolację od początku: `tenant_id` jako podstawowa kolumna w tabelach należących do klienta, indeksy z `tenant_id`, świadome ograniczenia unikalności, partycjonowanie dopiero po pomiarach, osobne ścieżki dla tabel globalnych i unikanie polityk, które robią ciężkie podzapytania dla każdego wiersza.

Warto też pamiętać, że izolacja w PostgreSQL nie rozwiązuje wszystkich problemów danych. Analityka, hurtownie, zdarzenia, indeks wyszukiwarki i pamięć podręczna muszą mieć własną izolację klientów. Jeżeli Elasticsearch albo Redis dostają klucz bez prefiksu klienta, ochrona w PostgreSQL nie uratuje danych poza bazą.

Kiedy izolacja w PostgreSQL nie wystarczy

Polityki wierszy są mocnym zabezpieczeniem procesu, ale nie są strategią bezpieczeństwa samą w sobie. Jeżeli klient wymaga osobnego regionu danych, osobnego tworzenia i odtwarzania kopii zapasowych, dedykowanego klucza szyfrowania, własnych okien utrzymaniowych albo certyfikacji, wspólne tabele z politykami wierszy mogą nie wystarczyć. Wtedy potrzebujesz osobnej bazy albo podejścia mieszanego.

Izolacja w bazie nie zastępuje też autoryzacji biznesowej. To, że użytkownik należy do organizacji klienta, nie znaczy, że może widzieć listę płac, eksportować wszystkie faktury albo usuwać projekt. Uprawnienia ról, plan subskrypcji, przełączniki funkcji i status konta nadal muszą być obsłużone w aplikacji i często odzwierciedlone w politykach.

Nie używaj izolacji w bazie jako pretekstu do pominięcia analizy zagrożeń. Trzeba przeanalizować administratorów, obsługę klienta, połączenia z innymi systemami, zdarzenia zewnętrzne, zadania w tle, kopie zapasowe, narzędzia analityczne, audyt, logi i narzędzia diagnostyczne. Wyciek może przyjść nie tylko z publicznego punktu dostępu aplikacji, ale też z "pomocnego" eksportu dla działu obsługi klienta.

Koszt wdrożenia: co naprawdę wpływa na budżet

Część serwerowa aplikacji dla wielu klientów z NestJS, izolacją w PostgreSQL, autoryzacją, podstawowym panelem i płatnościami zwykle zaczyna się od 160 000-300 000 PLN za sensowną pierwszą wersję. Zaawansowany produkt dla klientów firmowych z procesami, audytem, rozliczeniami, połączeniami z innymi systemami, importami danych i raportowaniem może iść wyżej. Sama polityka w bazie nie jest droga. Droga jest pewność, że nikt jej nie obejdzie.

Największe składniki kosztu to struktura danych, role i zasady uprawnień, migracje, testy izolacji, pula połączeń, połączenia z innymi systemami, audyt logów, narzędzia administracyjne i narzędzia obsługi klienta, import istniejących danych oraz monitorowanie działania. Jeżeli produkt ma funkcje AI lub wyszukiwanie w dokumentach, trzeba też rozwiązać izolację klientów w wektorach, wyszukiwaniu kontekstu i pamięci podręcznej.

GMI daje wstępną wycenę w 48h, ale stałą cenę dopiero po rozpoznaniu biznesu, projektu i technologii. W tym rozpoznaniu ustalamy sposób izolacji klientów, mapę danych, analizę zagrożeń, zakres pierwszej wersji, polityki dostępu w bazie, testy i ryzyka utrzymania. To uczciwsze niż obietnica "bezpiecznej aplikacji" na podstawie samego stosu technologicznego.

Lista kontrolna przed pracami programistycznymi

Ta lista powinna przejść przez dyrektora technologii, właściciela produktu i osobę odpowiedzialną za bezpieczeństwo przed pierwszym etapem prac nad częścią serwerową.

  • Które tabele należą do klienta, które są globalne, a które tylko administracyjne?
  • Czy każda tabela z danymi klienta ma identyfikator firmy, indeks i politykę dostępu w PostgreSQL?
  • Jak aplikacja ustawia kontekst firmy i czy jest on resetowany przy puli połączeń?
  • Które role mogą omijać polityki wierszy i czy aplikacja produkcyjna ich nie używa?
  • Czy mamy testy negatywne dla SELECT, INSERT, UPDATE, DELETE, eksportów i zadań w tle?
  • Jak izolujemy dane w pamięci podręcznej, wyszukiwarce, zdarzeniach, analityce, kopiach zapasowych i funkcjach AI?
  • Czy duzi lub regulowani klienci wymagają osobnej bazy albo podejścia mieszanego zamiast wspólnych tabel?

Jak GMI projektuje taką część serwerową

Zaczynamy od rozpoznania biznesu, projektu i technologii: mapujemy klientów, role, dane, połączenia z innymi systemami, rozliczenia, operacje administracyjne i ryzyka bezpieczeństwa. Dopiero potem decydujemy, czy system ma używać wspólnych tabel z politykami wierszy, osobnych baz, podejścia mieszanego czy kilku wariantów naraz. To ważne, bo zła decyzja o izolacji potrafi wymusić drogą migrację po pierwszych dużych klientach.

Technicznie najczęściej używamy NestJS, PostgreSQL, Prisma lub innej typowanej biblioteki do zapytań, Redis tam, gdzie potrzebna jest pamięć podręczna albo kolejka, Next.js dla panelu i React Native, jeśli produkt ma część mobilną. Kontrola dostępu w PostgreSQL jest częścią większej architektury: autoryzacja, dziennik audytu, monitorowanie działania, testy kontraktów oraz bezpieczne narzędzia obsługi klienta.

Biznesowo klient dostaje własność kodu źródłowego, brak uzależnienia od dostawcy, stałą cenę po rozpoznaniu projektu i jasny sposób utrzymania. To szczególnie ważne w produkcie abonamentowym, bo bezpieczeństwo nie jest jednorazową funkcją. Każda nowa tabela, połączenie z systemem i funkcja AI musi dalej respektować granicę klienta.

Źródła i dalsza lektura

PostgreSQL Row Security Policies: https://www.postgresql.org/docs/current/ddl-rowsecurity.html

AWS - rekomendacje izolacji wierszy dla PostgreSQL obsługującego wielu klientów: https://docs.aws.amazon.com/prescriptive-guidance/latest/saas-multitenant-managed-postgresql/rls.html

Supabase - przewodnik po kontroli dostępu do wierszy: https://supabase.com/docs/guides/database/postgres/row-level-security

PostgreSQL - konfiguracja sesji i ustawienia wykonywania: https://www.postgresql.org/docs/current/runtime-config-client.html

Prisma - surowy SQL i transakcje: https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries

GMI przewodnik o wydzielaniu zamówień w NestJS: /blog/nestjs-order-microservices-when-to-split

GMI przewodnik o NestJS, Prisma i PostgreSQL przy większej skali: /blog/nestjs-prisma-postgresql-at-scale

GMI tworzenie oprogramowania z AI jako częścią procesu: /services/ai-native-software-company

Najczęstsze pytania

Czy kontrola dostępu do wierszy w PostgreSQL wystarczy do zabezpieczenia aplikacji dla wielu klientów?
Nie wystarczy sama ochrona w bazie. Kontrola dostępu do wierszy w PostgreSQL jest bardzo mocną dodatkową obroną, ale nadal potrzebujesz autoryzacji w aplikacji, dobrych ról PostgreSQL, testów negatywnych, izolacji pamięci podręcznej, wyszukiwarki i zdarzeń oraz procesu przeglądu migracji. Chroni głównie tabele PostgreSQL, nie cały system.
Kiedy wybrać wspólne tabele z politykami wierszy zamiast osobnej bazy dla klienta?
Wspólne tabele z politykami wierszy mają sens, gdy wielu klientów korzysta z podobnego produktu, potrzebujesz niskiego kosztu infrastruktury, szybkich migracji i wspólnego wdrażania funkcji. Osobna baza jest lepsza przy silnych wymaganiach regulacyjnych, dedykowanych kopiach zapasowych i odtwarzaniu, osobnym regionie danych albo wymaganej izolacji dużego klienta.
Jak aplikacja ustawia kontekst klienta dla polityk w PostgreSQL?
Po uwierzytelnieniu aplikacja ustala firmę użytkownika i ustawia zmienną sesji PostgreSQL, np. `app.current_tenant`, zwykle na czas transakcji. Polityka porównuje identyfikator firmy w tabeli z tą zmienną. Przy puli połączeń trzeba pilnować resetu kontekstu, żeby następne żądanie nie odziedziczyło cudzej firmy.
Czy Prisma działa z kontrolą dostępu do wierszy w PostgreSQL?
Tak, ale Prisma nie jest granicą bezpieczeństwa. Polityki działają w PostgreSQL, więc zapytania Prisma też im podlegają, jeśli używasz właściwej roli i ustawiasz kontekst klienta na połączeniu lub transakcji. Wymaga to opakowań, testów i ostrożności przy surowym SQL oraz migracjach.
Ile kosztuje część serwerowa aplikacji dla wielu klientów z izolacją w PostgreSQL?
Sensowna pierwsza wersja z NestJS, izolacją w PostgreSQL, autoryzacją, panelem i płatnościami często zaczyna się od 160 000-300 000 PLN. Zaawansowany produkt dla klientów firmowych z procesami, audytem, połączeniami z innymi systemami i importami danych może kosztować więcej. Stałą cenę podajemy po rozpoznaniu projektu.
Czy izolacja w PostgreSQL zabezpiecza dane w pamięci podręcznej, wyszukiwarce i funkcjach AI?
Nie bezpośrednio. Polityki wierszy działają w PostgreSQL. Redis, Elasticsearch, zdarzenia, hurtownia danych, kopie zapasowe i dane używane przez funkcje AI muszą mieć własną izolację klientów: prefiksy kluczy, filtry, indeksy dla klienta albo osobne zasoby tam, gdzie wymaga tego ryzyko. Granica klienta musi istnieć w każdej warstwie, w której pojawiają się jego dane.

Treść zaktualizowano: 11 lipca 2026

Udostępnij artykuł:

Powiązane artykuły

Technologie

React Native czy aplikacje natywne w 2026: decyzja biznesowa, nie religia technologiczna

Najlepszy wybór nie zależy od tego, która technologia ma głośniejszych fanów, tylko od ryzyka produktu: czasu wejścia na rynek, kosztu utrzymania, dostępu do sprzętu, wydajności, publikacji i jakości w App Store. Praktyczna mapa decyzji dla właściciela firmy, dyrektora technicznego i lidera produktu.

Technologie

Mikroserwisy NestJS: kiedy wydzielić zamówienia z monolitu sprzedażowego?

Decyzyjny przewodnik dla dyrektora technologii i liderów sprzedaży internetowej: kiedy zostawić monolit, kiedy wydzielić obsługę zamówień oraz jak użyć NestJS, RabbitMQ, Redis i stopniowej modernizacji bez ryzyka dla finalizacji zamówienia.

Kontakt

Porozmawiajmy
o projekcie.

Masz pomysł na aplikację lub potrzebujesz wsparcia technologicznego? Napisz do nas — przygotujemy wstępną analizę i wycenę w 48 godzin. Po rozpoznaniu zakresu, projektu i technologii możemy zaproponować gwarancję ceny oraz umowę ze stałą ceną; to nasz wyróżnik na rynku.

Napisz do nas[email protected]
Odwiedź nas
GD
gmi.software Sp. z o.o.ul. Jana Heweliusza 11 / 819
80-890 Gdańsk, Polska
NIP: 5252816287KRS: 0000830003
gmi.
UsługiNasze projektyBlogAsystent briefuKontakt
LIFAINGI
Nominacja Mobile Trends Awards 2025 - aplikacja SFD
© 2026 gmi.software Sp. z o.o.
Polityka prywatnościRegulamin