Real-time w biznesie - dlaczego Twój konkurent wie o problemie 3 godziny przed Tobą

Piątek, 15:00. Generujesz raport tygodniowy. Czekasz 20 minut. Otwierasz. Widzisz, że we wtorek sprzedaż spadła o 40%. Dzwonisz do handlowca. "A, tak, klient X odwołał zamówienie, nie zdążyłem powiedzieć". Tracisz 3 dni na reakcję. 3 dni, w których mogłeś porozmawiać z klientem, zaproponować rabat, zrozumieć problem.

Twój konkurent ma dashboard real-time. We wtorek o 10:15, 15 minut po odwołaniu zamówienia, manager dostaje alert: "Klient X odwołał zamówienie na 45 000 PLN. Powód: brak potwierdzenia terminu dostawy." O 10:30 dzwoni do klienta. O 11:00 zamówienie jest przywrócone z potwierdzonym terminem.

Różnica? Nie technologia. Czas reakcji.

Czym jest real-time w kontekście biznesowym

Real-time to nie "dane odświeżają się co sekundę". To fundamentalna zmiana w sposobie, w jaki firma operuje:

System tradycyjny (raport): Coś się dzieje → dane są zbierane → ktoś generuje raport → ktoś go czyta → ktoś podejmuje decyzję → ktoś ją wykonuje. Cykl: godziny do dni.

System real-time: Coś się dzieje → system natychmiast informuje właściwą osobę → decyzja podejmowana jest w minutach → działanie natychmiast. Cykl: sekundy do minut.

To nie jest różnica stopnia. To różnica jakościowa. Firma z real-time nie jest "trochę lepsza" - gra w inną grę.

Gdzie real-time zmienia zasady

Sprzedaż: reakcja zamiast raportu

Bez real-time:

  • Spadek sprzedaży widać w raporcie tygodniowym / miesięcznym
  • Reakcja: spotkanie zespołu, analiza, plan działania, wdrożenie
  • Czas od problemu do reakcji: 1-4 tygodnie
  • Klienci odchodzą w tym czasie do konkurencji

Z real-time:

  • Dashboard pokazuje sprzedaż na żywo z porównaniem do analogicznego dnia / tygodnia / roku
  • Alert, gdy sprzedaż spada poniżej progu (np. -20% vs tydzień temu)
  • Manager widzi alert o 10:00, analizuje przyczynę do 10:30, podejmuje działanie do 11:00
  • Klient jest obsłużony tego samego dnia
# LiveView - dashboard aktualizuje się sam
def handle_info({:new_order, order}, socket) do
  stats = recalculate_stats(socket.assigns.stats, order)

  # Sprawdź alert
  if stats.today_vs_last_week < -0.20 do
    Notifications.send_alert(socket.assigns.manager_id,
      "Sprzedaż dziś: #{stats.today_total} PLN (-#{abs(stats.today_vs_last_week * 100)}% vs tydzień temu)")
  end

  {:noreply, assign(socket, stats: stats)}
end

Dashboard zarządu w Phoenix LiveView: wykres sprzedaży rysuje się punkt po punkcie, z każdą nową transakcją. Nie trzeba klikać "Odśwież". Nie trzeba generować raportu. Dane .

Magazyn: stan na żywo zamiast inwentaryzacji

Bez real-time:

  • Stany magazynowe aktualizowane raz dziennie (nocna synchronizacja)
  • Rano widać "50 sztuk", ale 10 zostało sprzedanych online nocą
  • Handlowiec obiecuje klientowi 50 sztuk. W magazynie jest 40
  • Inwentaryzacja raz na kwartał - 3 dni zamkniętego magazynu

Z real-time:

  • Każde wydanie z magazynu natychmiast aktualizuje stan w systemie
  • Handlowiec widzi aktualny stan (z dokładnością do sekundy) na LiveView
  • Gdy stan spada poniżej minimum - automatyczny alert + zamówienie do dostawcy
  • Ciągła inwentaryzacja zamiast kwartalnej: skanowanie bieżące, różnice widoczne natychmiast
Magazynier skanuje wydanie

PostgreSQL: UPDATE stany SET ilosc = ilosc - 1

NOTIFY stock_change

Phoenix PubSub → Wszystkie otwarte dashboardy

LiveView: stan aktualizuje się na ekranie handlowca

Jeśli stan < minimum → Oban: zamów u dostawcy

Od skanowania do aktualizacji na ekranie handlowca: poniżej 100 milisekund. Handlowiec zawsze wie, ile towaru ma w magazynie. Nie "ile było rano" - ile jest teraz.

Logistyka: tracking bez pytania

Bez real-time:

  • Klient dzwoni: "Gdzie jest moja paczka?"
  • Pracownik loguje się do panelu kuriera, szuka numeru przesyłki, czyta status, przekazuje klientowi
  • 5 minut na jedno pytanie × 50 pytań dziennie = 4 godziny dziennie na "gdzie jest moja paczka"

Z real-time:

  • Webhook od kuriera: status przesyłki zmienił się
  • System automatycznie aktualizuje status zamówienia
  • Klient widzi tracking w swoim panelu (LiveView - aktualizacja bez odświeżania)
  • Email/SMS wysyłany automatycznie przy zmianie statusu
  • Pracownik zajmuje się czymś wartościowszym niż kopiowanie statusów

Koszt "gdzie jest moja paczka": 4h × 220 dni × 50 PLN/h = 44 000 PLN/rok na odpowiadanie na pytanie, którego system powinien rozwiązywać automatycznie.

Produkcja: monitoring linii

Bez real-time:

  • Maszyna stoi 2 godziny, zanim ktoś zauważy
  • Awaria odkryta, gdy pracownik przychodzi po przerwie
  • Spadek wydajności widoczny w raporcie dziennym - ale jaka maszyna, o której godzinie?

Z real-time:

  • Czujnik wykrywa anomalię (temperatura, wibracje, prędkość)
  • Alert natychmiast do technika (push notification)
  • Dashboard produkcji: OEE (Overall Equipment Effectiveness) na żywo
  • Historia microawarii: "maszyna 3 miała 47 mikroprzestojów w tym tygodniu - wymaga przeglądu"

Finanse: cashflow na żywo

Bez real-time:

  • Stan konta sprawdzany raz dziennie rano
  • Faktura wystawiona w poniedziałek, zapłata sprawdzana w piątek
  • "Czy klient X już zapłacił?" - trzeba sprawdzić w banku

Z real-time:

  • Open Banking API: saldo i transakcje na żywo
  • Wpłata klienta → automatyczne sparowanie z fakturą → status "Opłacone"
  • Alert: "Klient Y nie zapłacił w terminie. Faktura #1234, 15 000 PLN, 7 dni po terminie"
  • Dashboard CFO: cashflow, należności, zobowiązania - na żywo

Dlaczego BEAM jest stworzony do real-time

Real-time w Phoenix LiveView nie jest "feature'em do włączenia". To domyślny tryb działania. I to nie przypadek - BEAM (maszyna wirtualna Erlanga/Elixira) został zaprojektowany do systemów telekomunikacyjnych, gdzie real-time to wymóg absolutny.

Miliony połączeń jednocześnie

Każdy użytkownik dashboardu to jedno połączenie WebSocket. BEAM obsługuje miliony jednoczesnych połączeń na jednym serwerze. 500 pracowników z otwartymi dashboardami? To nawet nie rozgrzewka.

Izolacja procesów

Dashboard zarządu, który przelicza roczne statystyki, nie spowalnia dashboardu magazyniera, który skanuje przesyłki. Każdy dashboard to osobny proces BEAM z osobną pamięcią. Crash jednego nie wpływa na inne.

PubSub bez infrastruktury

Phoenix PubSub to wbudowany system publish/subscribe. Nowe zamówienie w bazie → broadcast do wszystkich zainteresowanych dashboardów. Zero Redisa, zero Kafki, zero konfiguracji.

# Broadcast po zapisie zamówienia
def create_order(attrs) do
  case Repo.insert(changeset) do
    {:ok, order} ->
      Phoenix.PubSub.broadcast(MyApp.PubSub, "orders", {:new_order, order})
      Phoenix.PubSub.broadcast(MyApp.PubSub, "stats", {:recalculate})
      {:ok, order}
    error -> error
  end
end

# Każdy LiveView nasłuchujący na "orders" dostanie aktualizację
def mount(_params, _session, socket) do
  Phoenix.PubSub.subscribe(MyApp.PubSub, "orders")
  {:ok, assign(socket, orders: list_today_orders())}
end

Diff HTML zamiast pełnego renderowania

Gdy nowe zamówienie pojawia się na dashboardzie, LiveView nie przerysowuje całej strony. Wysyła tylko zmieniony fragment - nowy wiersz w tabeli, zaktualizowaną sumę, przesunięty punkt na wykresie. Transfer danych: bajty, nie kilobajty.

Od raportu do dashboardu - jak migrować

Krok 1: Zidentyfikuj Top 3 raporty

Które raporty generujesz najczęściej? Które trwają najdłużej? Które blokują decyzje? Zwykle to:

  1. Sprzedaż - dzienna, tygodniowa, miesięczna
  2. Stany magazynowe - dostępność produktów
  3. Należności - kto nie zapłacił

Krok 2: Zbuduj jeden dashboard

Zacznij od jednego. Nie od trzech, nie od całego BI. Jeden dashboard, który zastępuje najczęstszy raport.

Dashboard sprzedaży w LiveView:

  • Wykres sprzedaży dziennej (porównanie z zeszłym tygodniem/rokiem)
  • Top 10 produktów dnia
  • Top 10 klientów dnia
  • Alerty (spadki, rekordy, anomalie)
  • Filtry: data, region, handlowiec, kategoria

Wszystko aktualizuje się na żywo. Zero klikania "Generuj".

Krok 3: Dodaj alerty

Dashboard jest dla ludzi, którzy na niego patrzą. Alerty są dla ludzi, którzy nie mają czasu patrzeć na dashboard:

# Sprawdzaj co 15 minut
{"*/15 * * * *", CheckAlerts}

# Worker
def perform(_job) do
  if Sales.today_vs_average() < -0.3 do
    Slack.send("#sprzedaz", "Sprzedaż dziś -30% vs średnia. Sprawdź dashboard.")
  end

  if Inventory.critical_stock_items() |> length() > 0 do
    Email.send("magazyn@firma.pl", "Produkty poniżej stanu minimalnego",
      Inventory.critical_stock_items())
  end

  if Finance.overdue_invoices_total() > 100_000 do
    Slack.send("#finanse", "Zaległe faktury przekroczyły 100k PLN.")
  end

  :ok
end

Alerty nie zastępują dashboardu - uzupełniają go. Dashboard daje kontekst. Alert mówi "popatrz na dashboard, bo coś się dzieje".

Krok 4: Przenoś kolejne raporty

Każdy kolejny dashboard jest łatwiejszy, bo infrastruktura (LiveView, PubSub, alerty) jest już gotowa. Dodanie nowego dashboardu to dodanie nowego LiveView - dni, nie tygodnie.

Real-time to nie koszt - to przewaga

Firmy, które mają dane na żywo:

  • Reagują szybciej na problemy (minuty vs dni)
  • Decydują lepiej (dane aktualne, nie sprzed tygodnia)
  • Obsługują klientów lepiej (odpowiedź w sekundy, nie "sprawdzę i oddzwonię")
  • Tracą mniej na ręczne sprawdzanie i raportowanie
  • Widzą trendy wcześniej (spadek w poniedziałek, nie w piątkowym raporcie)

Twoja konkurencja albo już to ma, albo właśnie to buduje. Pytanie nie brzmi "czy potrzebujesz real-time" - brzmi "ile tracisz, nie mając go".

Chcesz zobaczyć, jak Twój najczęstszy raport może wyglądać jako dashboard real-time? Porozmawiajmy - zbudujemy prototyp na Twoich danych w kilka dni.