Fail open, fail closed - decizi o dată, pentru fiecare dependență

Fiecare serviciu extern pe care îl apelează sistemul tău va fi indisponibil la un moment dat. Nu „s-ar putea” - va fi. Singura întrebare e ce face sistemul tău în minutele alea, iar întrebarea asta are un răspuns corect per dependență, nu per sistem.

Cele două opțiuni

Fail closed: dependența e picată, deci operațiunea e refuzată. Sigur, evident, și ce face cea mai mare parte din cod din întâmplare, pentru că o excepție pe care n-a prins-o nimeni face fail closed implicit.

Fail open: dependența e picată, deci operațiunea continuă, iar munca rămasă intră în coadă și e marcată pentru un om. Cere design deliberat și un loc unde să ajungă marcajul.

Întrebarea care decide

Întreabă-te: dacă terțul ăsta e picat o oră, cine plătește?

Ia o verificare anti-bot pe un formular de programare. Dacă furnizorul nu e accesibil și faci fail closed, refuzi orice programare timp de o oră - ai transformat pana altcuiva în venitul tău pierdut, ca să eviți poate două formulare de spam. Fă fail open, acceptă programarea, marchează-o ca neverificată și ocupă-te manual de cele câteva proaste.

Acum ia-ți propriul rate limiter. Dacă cedează, nu ai niciun terț pe care să dai vina, iar fail open înseamnă că pur și simplu ai oprit o protecție exact în condițiile în care e cel mai probabil să fie nevoie de ea. Ăla face fail closed.

Tiparul care iese e același în fiecare sistem pe care l-am construit:

  • Fail open - livrarea de SMS-uri și e-mailuri, analytics și evenimentele de pixel, verificările anti-bot, sincronizarea de facturare și contabilitate, push-ul către CRM, căutarea de adrese. Orice lucru a cărui valoare e înregistrată în altă parte sau poate fi reconciliată mai târziu.
  • Fail closed - autorizarea plăților, autentificarea și verificările de sesiune, verificările de permisiuni, propriile tale rate limit-uri și validări, și orice ar putea lăsa un client să vadă datele altui client.

Fail open nu înseamnă „dai drumul și uiți”

Modul de eșec al unui fail open prost implementat e mai rău decât fail closed, pentru că e tăcut. Trei lucruri îl fac cinstit:

  • Înregistrarea poartă starea - unverified, invoice_pending - nu un comentariu într-un fișier de log.
  • Ceva reîncearcă, cu backoff, și renunță zgomotos, nu în surdină.
  • Cineva poate vedea coada. Un ecran de admin care listează ce așteaptă, cu un număr, văzut de un om care va observa dacă nu e zero.

Fără al treilea, n-ai construit reziliență. Ai construit un loc în care se adună probleme pe care nu le va găsi nimeni.

Scrie decizia undeva

Partea care contează cu adevărat nu e codul. E că decizia asta se ia o singură dată, explicit, pentru fiecare dependență - și se consemnează, ca următorul om să n-o inverseze din greșeală în timp ce repară altceva. Un tabel în documentul de arhitectură, cu trei coloane: dependența, comportamentul și o propoziție de ce. Zece minute, și închide o discuție care altfel s-ar relua în fiecare an.

Același raționament se aplică și lucrului pe care e scrisă decizia: un sistem ale cărui conturi nu le controlezi tu a făcut deja fail open, permanent. Despre asta e nota despre ce deții de fapt.