Eventual consistency – cichy wróg dobrego UX

Eventual consistency brzmi rozsądnie technicznie, ale w praktyce to często UX-owy koszmar. Zobacz, dlaczego i jak się przed tym bronić.

Czym jest eventual consistency?

Eventual consistency (czyli „ostateczna spójność”) to model spójności danych, który mówi tyle: „Nie gwarantuję, że dane są spójne teraz, ale będą… kiedyś.”

W praktyce oznacza to, że różne części systemu mogą przez chwilę widzieć różne wersje tych samych danych – i to jest akceptowalne. Warunkiem jest to, że po odpowiednim czasie wszystko się wyrówna, a dane staną się spójne globalnie.

Ten model stosuje się głównie w systemach rozproszonych, gdzie kluczowe są:

  • wysoka dostępność,
  • odporność na błędy,
  • szybkość działania lokalnych operacji.

Jeśli trzeba wybierać między dostępnością a natychmiastową spójnością – eventual consistency mówi: wybierz dostępność. Przetwarzanie odbywa się asynchronicznie, czasem w wielu krokach, czasem w kolejce, czasem z opóźnieniami.

Dlaczego eventual consistency to problem front-u?

Z perspektywy back-end-u, eventual consistency to sprytne rozwiązanie. Systemy rozproszone, mikroserwisy, skalowanie, odporność na błędy – wszystko się zgadza. Ale jeśli spojrzeć na to z poziomu użytkownika? Mamy mały dramat.

Wyobraź sobie taką sytuację:

Zamawiasz produkt w sklepie internetowym. Klikasz „Kup teraz”, pojawia się komunikat „Dziękujemy za zamówienie”, ale po odświeżeniu strony produkt nadal leży w koszyku. A w historii zamówień – cisza.

Minęły dopiero dwie sekundy. Back-end jeszcze „nie doszedł” do konsystencji. Technicznie wszystko działa. Ale dla użytkownika… coś tu się ewidentnie zepsuło. Problem jednak nie leży w samej eventual consistency jako takiej. To mechanizm o sensownych podstawach. Użyty bez refleksji, może sprawić, że doświadczenie użytkownika stanie się dziwnie… niespójne.

Oto klasyczna ścieżka bólu:

  • Coś idzie nie tak (timeout, rollback, błąd walidacji).
  • UI zostaje z niespełnioną obietnicą.
  • Użytkownik wykonuje akcję (np. dodaje komentarz).
  • Interfejs reaguje optymistycznie – pokazuje wynik od razu.
  • Back-end przetwarza żądanie asynchronicznie.

Talk is cheap, show me the code

Poniżej prosty przykład, który pokazuje, jak można zasymulować optymistyczne UI z konsekwencjami eventual consistency:

class Comment {
  constructor(
    public readonly authorId: string,
    public readonly postId: string,
    public readonly content: string
  ) {}
}

class CommentService {
  private readonly pendingComments = new Map<string, Comment>();

  add(comment: Comment): void {
    this.pendingComments.set(comment.postId, comment);
    this.sendToBackend(comment);
  }

  private sendToBackend(comment: Comment): void {
    setTimeout(() => {
      // Backend responds with success or failure
      const success = Math.random() > 0.2;

      if (success) {
        this.pendingComments.delete(comment.postId);
        return;
      }

      console.warn("Failed to add comment");
    }, 1500);
  }
}

Z punktu widzenia użytkownika komentarz pojawił się od razu. Ale co, jeśli po wywołaniu REST API back-end go odrzuci? UI tego nie wie, a użytkownik dostaje fałszywy sygnał, że wszystko się udało.

Jak zminimalizować koszmar?

Nie da się całkowicie pozbyć eventual consistency, ale można nauczyć się z nią żyć – projektując system tak, by nie szkodziła UX-owi.

Trzy zasady do bycia wygrywem z eventual consistency:

  • Zachowuj spójność lokalnie – cache’uj tymczasowe dane i pokazuj je jako „wstępne”, ale jasno oznaczone.
  • Komunikuj status – pokazywanie spinnera to za mało; potrzebne są stany: „oczekujące”, „w trakcie przetwarzania”, „niepowodzenie”.
  • Ostrożnie z optimistic UI – jeśli nie możesz pewnie przewidzieć sukcesu, nie obiecuj za wcześnie.

Podsumowanie: technologia to nie wszystko

Eventual consistency jest jak niewidzialna siła – działa w tle, ale ma realny wpływ na to, co widzi (i czuje) użytkownik. Jeśli tworzymy systemy, które mają być nie tylko poprawne technicznie, ale też intuicyjne i przyjazne, musimy pamiętać o jednym: użytkownika nie obchodzi, że back-end „jeszcze nie zdążył przetworzyć”. On po prostu chce, żeby to działało. Od razu.

Autor wpisu

blog@orbisbit.com

Komentarze

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *

Sprawdź również