[ Wtyczki ]

Platforma email marketingu — dziesięć wtyczek, dziesięć baz

Serwis do email marketingu na WordPressie złożony z dziesięciu wtyczek, każda z własną bazą danych. Zgody, wypisy, kolejkę i zdarzenia rozdziela połączenie.

Live · 2026 · PHP · WordPress · MySQL · Redis · REST API · DMARC

Potok

  1. 1

    em-zgody

  2. 2

    em-kampanie

  3. 3

    em-wysylka

  4. 4

    em-reputacja

4 etapy · 2026

O projekcie

Serwis, którego całą funkcję niesie dziesięć wtyczek WordPressa, a każda z nich ma WŁASNĄ BAZĘ DANYCH — osobne połączenie, osobny schemat, osobne migracje i osobną politykę kopii zapasowych. To nie jest jedna wtyczka podzielona na katalogi ani dziesięć prefiksów w jednej bazie. To dziesięć magazynów, które nawzajem się nie widzą.

Zacznę od decyzji, z której wynika cała reszta: GRANICA MODUŁU MA BYĆ FIZYCZNA, NIE UMOWNA. WordPress zakłada jedną bazę i jeden wspólny uchwyt do niej, więc granica oparta na prefiksie tabeli jest umową dżentelmeńską — łamie ją pierwsze zapytanie napisane w pośpiechu i łamie cicho, bo nic nie protestuje. Kiedy moduł nie ma poświadczeń do cudzej bazy, nie napisze zapytania, które ją czyta. Nie dlatego, że nie wolno, tylko dlatego, że nie ma czym.

Cena jest wysoka i płaci się ją świadomie: MIĘDZY BAZAMI NIE MA ZŁĄCZEŃ ANI WSPÓLNYCH TRANSAKCJI. Spójność przestaje być własnością silnika i staje się obowiązkiem kodu — a kto nie umie powiedzieć, jak ją opłaci, ten nie powinien dzielić. Tutaj płaci się skrzynką nadawczą: zmiana i zapis o niej trafiają do bazy źródłowej W TEJ SAMEJ TRANSAKCJI, osobny proces przenosi zapis do modułu docelowego, a odbiorca stosuje go IDEMPOTENTNIE, więc ten sam zapis dostarczony drugi raz nie robi nic. Nie ma tu dwufazowego zatwierdzania i nie ma udawania, że dziesięć baz jest jedną.

Najważniejszym zbiorem w całym systemie nie są subskrybenci ani treść kampanii, tylko LISTA WYPISÓW. Ma trzy własności, których żaden inny magazyn nie potrzebuje. Jest dopisywana, nigdy nadpisywana. Jest sprawdzana W MOMENCIE WYSYŁKI, a nie kolejkowania — bo kampania do dwustu tysięcy adresów schodzi godzinami, a człowiek, który wypisał się w trzeciej godzinie, ma nie dostać wiadomości zakolejkowanej w pierwszej. I nie wolno jej odtworzyć z wczorajszej kopii zapasowej: starsza lista wypisów to lista bez wczorajszych sprzeciwów, więc jej przywrócenie wysyła wiadomości do ludzi, którzy je odwołali. Odtwarzanie idzie wyłącznie do przodu, ze strumienia zdarzeń.

ZGODA TO DOWÓD, NIE ZNACZNIK. Pole z wartością „tak” jest przy skardze warte tyle co nic: nie mówi kiedy, skąd ani na co człowiek się zgodził. Rejestr trzyma moment, adres formularza, identyfikator źródła, potwierdzenie podwójnej zgody i — to jest ta rzecz, której prawie nikt nie robi — TREŚĆ KLAUZULI W WERSJI, którą zapisujący się miał przed oczami. Klauzula zmienia się co kilka miesięcy; bez wersjonowania po roku nie da się odpowiedzieć na jedyne pytanie, które ktokolwiek zada.

WYSYŁKA NIE MA JEDNEGO TEMPA, bo odbiorcy go nie mają. Gmail, Outlook, Onet, WP i Interia mają osobną tolerancję na liczbę połączeń i wiadomości w oknie czasu, a przy odrzuceniu zachowują się różnie. Jedna globalna wartość „X na godzinę” albo marnuje przepustowość, albo wpada w dławienie i psuje reputację domeny nadawczej. Kolejka liczy okno OSOBNO DLA KAŻDEJ DOMENY ODBIORCY i po odpowiedzi z kodem 4xx cofa tempo dla tej jednej domeny, zamiast dobijać się tą samą częstotliwością.

Odbicia trzeba KLASYFIKOWAĆ, a nie liczyć. Twarde odbicie to adres, który nie istnieje — idzie na listę wypisów od razu, bo każda kolejna próba jest już tylko sygnałem dla filtrów, że nadawca nie sprząta listy. Miękkie to pełna skrzynka albo chwilowa odmowa: ponowienia z limitem, a po serii nieudanych również wypis. Najcięższa jest skarga z pętli zwrotnej — natychmiastowy wypis ORAZ znacznik na źródle pozyskania, bo źródło produkujące skargi jest prawdziwym problemem, a pojedynczy adres tylko jego objawem.

Współczynnik otwarć przestał być miarą i sprzedawanie go jako miary jest nieuczciwe. Ochrona prywatności w poczcie Apple pobiera obrazy Z WYPRZEDZENIEM, więc piksel zgłasza otwarcie, którego nie było — a ponieważ dotyczy części odbiorców, wynik nie jest nawet porównywalny w czasie z własnym wynikiem sprzed roku. Zdarzenia maszynowe są więc oznaczane osobno, raport pokazuje je jako odrębną warstwę i NIE WOLNO IM napędzać automatyzacji: ścieżka „otworzył, więc wyślij przypomnienie” na wstępnie pobranym pikselu wysyła przypomnienie komuś, kto nie zrobił nic.

Żądanie usunięcia danych jest przy dziesięciu bazach trudniejsze, dlatego jest opisane, a nie improwizowane. Rejestr wskazuje, który magazyn trzyma dane osobowe i co „usunięcie” w nim znaczy: subskrybent znika, strumień zdarzeń zostaje zanonimizowany (agregaty przeżywają, powiązanie z człowiekiem nie), a na liście wypisów zostaje JEDNOKIERUNKOWY SKRÓT adresu. Ten wyjątek jest sednem sprawy: gdyby usunięcie skasowało również zapis o sprzeciwie, ten sam adres wgrany za pół roku z nowego pliku dostałby kolejną kampanię. Skrót pozwala odpowiedzieć na pytanie „czy ten adres się wypisał” bez przechowywania adresu.

Skoro złączeń nie ma, raport nie powstaje z zapytania przez dziesięć baz, tylko z PROJEKCJI. Moduł raportowy ma własną bazę, do której pozostałe wysyłają zdarzenia, i przelicza z nich gotowe zestawienia. To jedyne miejsce w systemie, gdzie dane z różnych modułów się spotykają, i jest z założenia opóźnione o sekundy. Ta zwłoka jest ceną, którą widać — brak złączeń przez dziesięć baz to cena, której nie widać, ale to ona utrzymuje granice przy życiu.

Problem

Platformy do email marketingu trzymają wszystko w jednej bazie, więc zgoda, wypis, strumień zdarzeń i treść kampanii mają wspólną politykę kopii, wspólną retencję i wspólny promień rażenia. Nieudana migracja przy edytorze szablonów sięga rejestru zgód, a odtworzenie bazy z wczorajszej kopii przywraca do wysyłki ludzi, którzy wczoraj się wypisali.

Rozwiązanie

Dziesięć wtyczek, każda z własną bazą i własnym połączeniem — granica modułu jest fizyczna zamiast umownej. Zmiany między bazami idą skrzynką nadawczą zapisywaną w tej samej transakcji co sama zmiana, raport powstaje z projekcji zamiast ze złączeń, a lista wypisów ma osobną politykę odtwarzania: wyłącznie do przodu.

Funkcje

  • dziesięć wtyczek z osobnym połączeniem — moduł nie ma czym sięgnąć po cudze dane
  • zmiany między bazami skrzynką nadawczą zapisywaną w tej samej transakcji
  • odbiorca stosuje zapis idempotentnie: dostarczony dwa razy robi to samo, co raz
  • wypis sprawdzany w momencie wysyłki, nie kolejkowania — kampania schodzi godzinami
  • rejestr zgód z treścią klauzuli w wersji, którą widział zapisujący się
  • tempo liczone osobno dla każdej domeny odbiorcy, z cofaniem po odpowiedzi 4xx
  • odbicia klasyfikowane: twarde od razu do wypisów, miękkie z limitem ponowień
  • otwarcia maszynowe oznaczone osobno i odcięte od wyzwalaczy automatyzacji
  • usunięcie danych zostawia na liście wypisów jednokierunkowy skrót adresu

Moduły

  • em-subskrybenci

    wtyczka i baza profili

    Trzyma ludzi i listy: profile, pola własne, przynależność do list oraz definicje segmentów.

    • profil ma jeden adres i jedną historię, także gdy trafił z kilku źródeł naraz
    • pola własne opisane w schemacie, a nie upchnięte w worku serializowanych metadanych
    • segment jest zapisanym zapytaniem, nie wynikiem zamrożonym w chwili utworzenia
    • scalanie duplikatów zachowuje NAJWCZEŚNIEJSZĄ zgodę i NAJPÓŹNIEJSZY sprzeciw
    • import pliku przechodzi przez tę samą bramkę zgody, co zapis z formularza
  • em-zgody

    wtyczka i rejestr dowodowy

    Zapisuje, na co dokładnie i kiedy człowiek się zgodził — w formie, którą da się komuś pokazać.

    • wpis dopisywany, nigdy nadpisywany; zmiana zdania to kolejny wpis, nie edycja
    • treść klauzuli zapisana W WERSJI widzianej przez zapisującego się
    • moment, źródło, adres formularza i potwierdzenie podwójnej zgody przy każdym wpisie
    • adres IP skracany przed zapisem — do dowodu wystarcza, do profilowania już nie
    • wycofanie zgody wypycha wpis do em-wypisy w tej samej transakcji, skrzynką nadawczą
  • em-wypisy

    wtyczka i magazyn o najwyższej integralności

    Jedna globalna lista adresów, do których nie wolno wysłać — sprawdzana przy każdej wiadomości.

    • sprawdzenie przy WYSYŁCE, nie przy kolejkowaniu; duża kampania schodzi godzinami
    • dopisywana wyłącznie do przodu — operacji usunięcia z tej listy po prostu nie ma
    • odtworzenie z kopii zapasowej zablokowane: starsza lista gubi nowsze sprzeciwy
    • po usunięciu danych osobowych zostaje jednokierunkowy skrót adresu
    • własna kopia i własny harmonogram, niezależne od polityki reszty systemu
  • em-tresci

    wtyczka i baza szablonów

    Szablony i bloki wiadomości z wersjonowaniem oraz podglądem w programach pocztowych.

    • wysłana kampania trzyma ODNOŚNIK DO WERSJI szablonu, a nie do szablonu
    • warstwa tekstowa obowiązkowa — wiadomość bez niej nie przechodzi do kolejki
    • personalizacja z wartością zastępczą; brak danych nie zostawia dziury w zdaniu
    • odnośniki przepisywane na śledzące przy składaniu wiadomości, nie w edytorze
    • kontrola wagi: powyżej progu Gmail obcina wiadomość razem ze stopką wypisu
  • em-kampanie

    wtyczka i baza kampanii

    Kampanie, harmonogram i testy wariantów — wszystko rozstrzygnięte przed wejściem do kolejki.

    • wariant losowany na rozłącznych podzbiorach, a nie na „pierwszych dziesięciu procentach”
    • minimalna próba i minimalny czas przed ogłoszeniem zwycięzcy; wcześniej to szum
    • okno wysyłki liczone w STREFIE ODBIORCY, nie nadawcy
    • lista odbiorców powstaje raz, przy starcie — inaczej ten sam raport dwa razy kłamie
    • kampania zatrzymana zostaje zatrzymana: wznowienie dosyła resztę, nie zaczyna od nowa
  • em-wysylka

    wtyczka i kolejka

    Zamienia kampanię na pojedyncze wiadomości i wypuszcza je w tempie, które znosi odbiorca.

    • okno tempa liczone OSOBNO dla każdej domeny odbiorcy
    • odpowiedź 4xx cofa tempo tej domeny zamiast wywoływać ponowienie tak samo często
    • klucz idempotencji na parę kampania–odbiorca; wznowiony proces nie wysyła drugi raz
    • stan zapisywany po każdej porcji, więc przerwana wysyłka wznawia się, nie startuje od zera
    • rozgrzewanie nowej domeny nadawczej: wolumen rośnie etapami, najpierw najlepsze segmenty
  • em-zdarzenia

    wtyczka i strumień dopisywany

    Dostarczenia, otwarcia, kliknięcia i odbicia jako strumień, z którego liczy się wszystko inne.

    • tabela dopisywana i partycjonowana czasem; czyszczenie to odpięcie partycji, nie kasowanie wierszy
    • otwarcia maszynowe, czyli wstępne pobrania obrazu, oznaczane osobno od ludzkich
    • adres IP skracany przy zapisie — pełny nie trafia do magazynu nawet na chwilę
    • krótka retencja zdarzeń surowych, długa dla agregatów; to dwie różne decyzje
    • przekierowanie kliknięcia działa, nawet gdy zapis zdarzenia zawiedzie — najpierw człowiek
  • em-reputacja

    wtyczka i baza dostarczalności

    Pilnuje tego, co rozstrzyga, czy wiadomość w ogóle dojdzie: uwierzytelnienia, odbić i skarg.

    • SPF, DKIM i DMARC sprawdzane cyklicznie, a nie raz przy wdrożeniu
    • twarde odbicie to natychmiastowy wypis; miękkie — ponowienia z limitem, potem też wypis
    • skarga z pętli zwrotnej znaczy ŹRÓDŁO POZYSKANIA, nie tylko pojedynczy adres
    • skrzynki kontrolne u głównych dostawców: pomiar zamiast wiary we własne statystyki
    • próg skarg na oknie kroczącym; przekroczenie wstrzymuje wysyłkę przed człowiekiem
  • em-sciezki

    wtyczka i maszyna stanów

    Automatyzacje, w których każdy subskrybent ma własną pozycję w ścieżce i jeden zapis stanu.

    • stan per subskrybent i ścieżka — bez globalnego licznika i bez zadania przelatującego listę
    • każdy krok ma klucz idempotencji; padnięcie procesu w połowie nie dubluje wiadomości
    • zmiana definicji NIE przenosi na nową wersję ludzi będących już w drodze
    • warunek wejścia sprawdzany ponownie przed krokiem — dane mogły się zmienić po drodze
    • zdarzenia maszynowe odcięte od wyzwalaczy: ścieżka rusza na sygnał człowieka
  • em-raporty

    wtyczka i projekcje odczytowe

    Jedyne miejsce, w którym dane z dziesięciu baz się spotykają — jako przeliczone zestawienia.

    • projekcje budowane ze zdarzeń, bo złączeń między bazami nie ma i nie będzie
    • opóźnienie liczone w sekundach i POKAZANE w interfejsie, a nie przemilczane
    • otwarcia ludzkie i maszynowe w osobnych kolumnach; jedna wspólna suma kłamie
    • projekcja jest odtwarzalna: przelicza się od zera z zachowanego strumienia
    • eksport niesie zakres dat, wersję definicji metryki i moment przeliczenia

Architektura

Podstawa
WordPress jako powłoka administracyjna; dziesięć wtyczek z własnym cyklem wydawniczym i bez wspólnego kodu poza kontraktem zdarzeń
Bazy danych
dziesięć osobnych baz MySQL, dziesięć połączeń, dziesięć zestawów migracji; żaden moduł nie dostaje poświadczeń do cudzej
Granica modułów
fizyczna zamiast umownej — brak uchwytu do cudzych danych, a nie zakaz pilnowany w przeglądzie kodu
Spójność między bazami
skrzynka nadawcza zapisywana w tej samej transakcji co zmiana, przenoszenie osobnym procesem, idempotentne stosowanie u odbiorcy
Kolejka
Redis na porcje robocze, stan trwały w MySQL; wznowienie po awarii bez ponownej wysyłki dzięki kluczom idempotencji
Tempo wysyłki
okna liczone osobno per domena odbiorcy, cofanie po odpowiedzi 4xx, etapowe rozgrzewanie nowej domeny nadawczej
Lista wypisów
sprawdzana przy wysyłce, dopisywana wyłącznie do przodu, odtwarzanie z kopii zapasowej zablokowane z założenia
Rejestr zgód
wersja klauzuli, źródło, adres formularza i podwójna zgoda przy każdym wpisie; adres IP skracany przed zapisem
Usunięcie danych
rejestr magazynów z danymi osobowymi i definicja usunięcia dla każdego; na liście wypisów zostaje jednokierunkowy skrót
Śledzenie
przekierowanie przed zapisem zdarzenia; otwarcia maszynowe oznaczone osobno i odcięte od automatyzacji
Uwierzytelnienie nadawcy
SPF, DKIM i DMARC kontrolowane cyklicznie, pętla zwrotna wpięta u głównych dostawców, skrzynki kontrolne w monitoringu
Raportowanie
projekcje zamiast złączeń, opóźnienie pokazane w interfejsie, pełne przeliczenie od zera ze strumienia zdarzeń
Kopie zapasowe
osobny harmonogram i osobna polityka odtwarzania dla każdej z dziesięciu baz; jedna decyzja nie obejmuje wszystkich magazynów

Technologie

  • PHP
  • WordPress
  • MySQL
  • Redis
  • REST API
  • DMARC

Autor

  • Zdjęcie: Mariusz PerzyńskiMariusz PerzyńskiClient Relations & Operations

[ Kontakt ]

Chcesz podobne rozwiązanie w swojej firmie?

Opowiedz nam o swoim pomyśle — wrócimy z konkretną propozycją i wyceną.

Automatic AI

hello@automaticai.pl · automaticai.pl