Dacă ai fost vreodată într-o ședință în care cineva merge la tablă, desenează o căsuță etichetată „sistemul”, apoi o căsuță mai mică în interior etichetată „API”, apoi încă zece căsuțe în jur, iar o oră mai târziu nimeni nu se mai înțelege asupra a ce trebuiau să discute, ai experimentat problema centrală a diagramelor de arhitectură. Diagramele nu sunt de fapt problema. Lipsa unei convenții comune pentru la ce nivel de zoom ești este problema.
Vorbim despre sistem ca un singur lucru într-un ecosistem mai larg? Sau despre unitățile deployabile din interiorul sistemului? Sau despre modulele din interiorul uneia dintre acele unități? Sau despre cod? Fiecare dintre astea e o conversație utilă. Amestecarea lor în aceeași diagramă e modul în care obții o tablă cu optzeci de căsuțe pe care nimeni nu le poate citi.
Modelul C4 al lui Simon Brown rezolvă asta. Este, în funcție de cum numeri, fie o contribuție extrem de modestă la ingineria software, fie o revoluție subapreciată. E o convenție. Patru niveluri standard de zoom pentru a vorbi despre un sistem. Fiecare nivel are un domeniu clar, un set clar de elemente legitime și o întrebare clară la care răspunde. Când echipa cade de acord să folosească convenția, conversațiile devin mai rapide, diagramele devin mai clare, iar tabla nu mai arată ca un Jackson Pollock.
Lecția asta trece prin cele patru niveluri, cu un exemplu lucrat pentru un mic produs SaaS și câteva opinii despre când să nu folosești C4.
Cele patru niveluri
C4 vine de la Context, Container, Component, Code. Fiecare e un nivel de zoom. Te muți de la cel mai larg (Context) la cel mai detaliat (Code), iar la fiecare nivel arăți doar elementele potrivite pentru acel zoom.
Nivelul 1: System Context. Sistemul pe care îl construiești, situat în lumea mai largă. Arată sistemul ca o singură căsuță, utilizatorii umani („actorii”) și sistemele externe de care sistemul tău depinde sau cu care se integrează. Audiența e largă: oricine din business, tehnic sau nu, ar trebui să poată citi această diagramă. Întrebarea la care răspunde e „ce e chestia asta și cu ce vorbește?”
Nivelul 2: Container. Face zoom în sistem din nivelul 1. Arată unitățile deployabile sau rulabile din interior: web frontend-ul, serviciul de API, baza de date, message broker-ul, procesul worker, cache-ul. „Container” aici e un termen Brown care precede Docker cu ani și se referă la „orice lucru care găzduiește cod sau date”, nu specific la un container Linux, deși în 2026 majoritatea containerelor în acest sens rulează în interiorul containerelor reale în sensul Docker. Audiența e tehnică: dezvoltatori, SRE, arhitecți. Întrebarea la care răspunde e „ce rulează unde și cum vorbesc lucrurile alea între ele?”
Nivelul 3: Component. Face zoom într-un container din nivelul 2. Arată modulele majore, serviciile sau grupările logice din interiorul acelui container. Pentru un serviciu de API, componentele ar putea fi auth, orders, products, billing. Pentru un frontend, componentele ar putea fi stratul de routing, contextul de auth, stratul de data fetching, design system-ul. Audiența e dezvoltatorii care lucrează la acel container. Întrebarea la care răspunde e „cum e organizat intern acest container?”
Nivelul 4: Code. Face zoom într-o componentă din nivelul 3 și arată clasele, interfețele sau funcțiile reale. Diagramă UML de clase, în esență, scoped la o singură componentă. Audiența e oricine implementează componenta. Întrebarea la care răspunde e „care sunt obiectele de cod efective implicate?”
Trucul lui C4 e că desenezi nivelurile de care ai nevoie și le sari pe cele de care nu. Majoritatea conversațiilor utile au loc la nivelurile 1, 2 și 3. Nivelul 4 e rareori merită desenat pentru că în momentul în care ești la nivelul de clasă, e aproape întotdeauna mai rapid să citești codul decât să menții o diagramă care se învechește în momentul în care cineva refactorizează. Brown însuși zice că nivelul 4 e opțional și majoritatea echipelor îl sar.
Celălalt aspect util: fiecare nivel îți permite să ai o conversație la acel nivel fără să tragi celelalte niveluri în ea. Când product owner-ul întreabă „sistemul se integrează cu Stripe?” arăți spre diagrama Context. Nu explici și că Stripe e apelat din bean-ul Spring BillingService din pachetul payments al containerului api. Nu le pasă. Vor să știe dacă Stripe e în peisaj. Diagrama Context spune da.
Exemplu lucrat: un mic produs SaaS
Hai să desenăm toate cele trei niveluri utile pentru un produs SaaS mic ipotetic. Hai să-i spunem ChartSmith, o unealtă online pentru desenat grafice. Utilizatorii se înregistrează, se loghează, construiesc grafice, le salvează și le exportă. Graficele sunt stocate într-o bază de date, exportate via un worker de background, facturate lunar prin Stripe, iar email-urile de confirmare ies prin SendGrid. E un frontend React, un API Node, o bază de date Postgres, un cache Redis și un worker Python de export în spatele unei job queue.
Acel paragraf e sistemul în engleză simplă (ei bine, română aici). Acum să vedem cum arată fiecare nivel C4.
Nivelul 1: System Context
Diagrama Context arată ChartSmith ca o singură căsuță, oamenii care îl folosesc și sistemele externe cu care se integrează.
flowchart LR
user(["ChartSmith user"])
admin(["ChartSmith admin"])
chartsmith["<b>ChartSmith</b><br/><i>Web app for building<br/>and exporting charts</i>"]
stripe["<b>Stripe</b><br/><i>Subscription payments</i>"]
sendgrid["<b>SendGrid</b><br/><i>Transactional email</i>"]
s3["<b>AWS S3</b><br/><i>Export storage</i>"]
user --> chartsmith
admin --> chartsmith
chartsmith --> stripe
chartsmith --> sendgrid
chartsmith --> s3
classDef person fill:#e6f4f1,stroke:#0d9488,color:#0c1419
classDef sys fill:#0d9488,stroke:#0d9488,color:#ffffff
classDef ext fill:#fff5e6,stroke:#c89200,color:#5a3e00
class user,admin person
class chartsmith sys
class stripe,sendgrid,s3 ext
Observă ce nu e pe această diagramă. Nu se menționează baza de date, sau cache-ul, sau dacă API-ul e REST sau GraphQL, sau dacă frontend-ul e React. Acele detalii aparțin nivelului 2. Diagrama Context e pentru conversația „aici e cutia, aici e lumea, aici sunt liniile dintre ele”. E diagrama pe care o pui pe prima pagină a unui design doc, cea pe care o arăți unui stakeholder non-tehnic și cea care ar trebui să fie citibilă în cincisprezece secunde.
Actorii sunt oamenii. Căsuța sistemului e ce construim. Sistemele externe sunt dependențe pe care nu le controlăm. Trei dependențe externe pentru un mic SaaS e normal; un sistem real tipic are între trei și treizeci, în funcție de cât de matur e produsul.
Nivelul 2: Container
Facem zoom în căsuța ChartSmith și arătăm ce e înăuntru.
flowchart TB
user(["ChartSmith user"])
subgraph chartsmith ["ChartSmith"]
direction TB
spa["<b>Web app</b><br/><i>React, Vite</i>"]
api["<b>API</b><br/><i>Node.js, Express</i>"]
worker["<b>Export worker</b><br/><i>Python</i>"]
db[("<b>Database</b><br/><i>PostgreSQL</i>")]
cache[("<b>Cache</b><br/><i>Redis</i>")]
queue["<b>Job queue</b><br/><i>Redis + BullMQ</i>"]
end
subgraph external ["External services"]
direction TB
stripe["<b>Stripe</b>"]
sendgrid["<b>SendGrid</b>"]
s3["<b>AWS S3</b>"]
end
user --> spa
spa --> api
api --> db
api --> cache
api --> queue
queue --> worker
api --> stripe
api --> sendgrid
worker --> s3
classDef person fill:#e6f4f1,stroke:#0d9488,color:#0c1419
classDef ext fill:#fff5e6,stroke:#c89200,color:#5a3e00
classDef boundary fill:transparent,stroke:#0d9488,stroke-dasharray: 5 5
class user person
class stripe,sendgrid,s3 ext
class chartsmith,external boundary
Asta e diagrama pe care dezvoltatorii și SRE-ii se ceartă. Arată unitățile deployabile reale, alegerile tehnologice pentru fiecare și protocoalele dintre ele. Șase containere e un sistem mic. Un SaaS de dimensiune medie va avea zece până la cincisprezece containere pe această diagramă. Un sistem enterprise mare va avea atât de multe încât îl împarți în mai multe diagrame Container, una per sub-sistem logic, și asta e ok.
Câteva convenții care merită notate. Bazele de date primesc forma de cilindru (ContainerDb în sintaxa Mermaid C4). Fiecare container are o etichetă, o tehnologie și o descriere de o linie. Fiecare săgeată e etichetată cu ce face și ce protocol folosește. Acele etichete par exagerate prima dată când desenezi diagrama și sunt esențiale a treia oară când o privești șase luni mai târziu întrebându-te de ce naiba API-ul vorbește cu Redis.
Diagrama Container e și locul unde poți citi topologia de deployment. Fiecare container din diagramă devine unul sau mai multe procese în producție. Web app-ul e servit dintr-un CDN. API-ul rulează ca o flotă de procese Node în spatele unui load balancer. Baza de date e un Postgres gestionat. Cache-ul e un Redis gestionat. Worker-ul e o flotă separată de procese Python. Nimic din astea nu e în diagramă explicit, dar totul e implicat de care căsuțe există.
Nivelul 3: Component
Facem zoom în containerul API și arătăm modulele majore din interior.
flowchart TB
spa["Web app"]
subgraph api ["API container"]
direction TB
router["<b>HTTP router</b><br/><i>Express, auth middleware</i>"]
subgraph features ["Feature components"]
direction LR
auth["<b>Auth</b>"]
charts["<b>Charts</b>"]
exports["<b>Exports</b>"]
billing["<b>Billing</b>"]
notifications["<b>Notifications</b>"]
end
data["<b>Data access</b><br/><i>Postgres + Redis repos</i>"]
end
storage[("DB / Cache / Queue")]
extsvc["Stripe / SendGrid"]
spa --> router
router --> auth
router --> charts
router --> exports
router --> billing
auth --> data
charts --> data
exports --> data
billing --> data
billing --> notifications
auth --> notifications
data --> storage
exports --> storage
notifications --> extsvc
billing --> extsvc
classDef ext fill:#fff5e6,stroke:#c89200,color:#5a3e00
classDef external fill:#f0f4f8,stroke:#5a6a73,color:#0c1419
classDef boundary fill:transparent,stroke:#0d9488,stroke-dasharray: 5 5
class extsvc ext
class spa,storage external
class api,features boundary
Diagrama Component arată organizarea internă a API-ului. Șapte componente, fiecare cu o responsabilitate clară. Granițele se mapează pe foldere în repository, mai mult sau mai puțin. Dezvoltatorii noi care se alătură echipei API se uită la această diagramă înainte să se uite la cod, pentru că le spune unde să găsească lucrurile. „Unde e apelat Stripe?” Componenta Billing. „Unde e hashing-ul de parolă?” Componenta Auth. „Unde sunt query-urile SQL?” Componenta Data access, și doar acolo.
Convenția care își merită aici banii e că componentele ar trebui să aibă single responsibilities și ar trebui să comunice prin interfețe clare. Dacă desenezi diagrama Component și descoperi că fiecare componentă vorbește cu fiecare altă componentă, ăsta e un semn că containerul tău și-a pierdut structura internă, iar diagrama face muncă utilă scoțând asta la suprafață.
În mod tipic ai desena o diagramă Component pentru fiecare container major care e suficient de complex încât să o merite. Web app-ul ar putea primi propria diagramă Component arătând structura frontend-ului. Worker-ul de export ar putea primi una arătând pipeline-ul de rendering. Baza de date nu are nevoie de una. Componentele din interiorul unei baze de date nu prea există într-un mod despre care C4 vorbește.
Nivelul 4: Code, și de ce de obicei îl sărim
Nivelul 4 ar face zoom într-o componentă (să zicem componenta Auth) și ar arăta clasele reale: UserRepository, SessionService, PasswordHasher, LoginController și așa mai departe, cu relațiile dintre ele. Teritoriu de diagramă UML de clase.
În practică aproape nimeni nu desenează astea și aproape nimeni nu ar trebui. Motivul e că diagramele de nivel 4 sunt expirate în ziua în care le desenezi. Structurile de clase se schimbă în fiecare săptămână pe măsură ce echipa refactorizează. Menținerea unei diagrame UML de clase desenate manual e o taxă pe care nimeni nu se oferă voluntar să o plătească, iar diagramele de clase generate de IDE sunt corecte dar rareori utile pentru că arată fiecare clasă fără curatorialitate.
Excepția e când documentezi o bucată de cod deosebit de subtilă: o mașină de stări, un parser, un pattern care i-a luat cuiva trei zile să-l descifreze și i-ar lua același trei zile unui mentenancer viitor să-l re-deducă fără ajutor. În acele cazuri, o diagramă de nivel 4 își merită banii. Altfel, codul tău e diagrama de nivel 4. Citește-l.
Ghidarea proprie a lui Brown e că nivelurile 1 până la 3 acoperă aproximativ 95% din conversațiile arhitecturale utile. Eu am descoperit că asta e aproximativ corect.
Când să nu folosești C4
C4 nu e unealta potrivită pentru fiecare situație. Câteva cazuri în care convenția e exagerată sau pur și simplu greșită.
Sisteme foarte mici. O singură funcție Lambda susținută de DynamoDB înseamnă două căsuțe. Nu ai nevoie de o diagramă Context, o diagramă Container și o diagramă Component pentru două căsuțe. O singură schiță e suficientă.
Prototipuri foarte timpurii. Când încerci să decizi dacă o idee e măcar fezabilă, desenarea de diagrame C4 formale te încetinește. O schiță de pe spatele unui plic cu căsuțe scrise de mână e mai bună. C4 începe să-și merite banii odată ce sistemul are formă și sunt stakeholder-i cu care să comunici.
Diagrame specializate care au propriile lor convenții. Sequence diagrams, mașini de stări, diagrame de topologie de rețea, ERD-uri, diagrame de deployment, diagrame de dataflow, fluxuri de proces BPMN: toate astea au propriile lor convenții stabilite și C4 nu e un înlocuitor pentru ele. C4 acoperă structura. Nu acoperă comportament, forme de date sau procese. Folosește unealta potrivită pentru întrebare.
Echipe care au deja o convenție diferită. Dacă organizația ta a standardizat pe diagrame de componente UML 2, sau ArchiMate, sau o convenție internă pe care toată lumea o citește fluent, trecerea la C4 e mai ales cost social. Valoarea lui C4 e în mare parte că toată lumea din echipă îl folosește la fel, iar orice convenție consistentă bate o lipsă de convenție.
Regula generală: folosește C4 când explici un sistem non-trivial unor oameni care nu au fost în cameră când a fost proiectat. Sări peste el când audiența și artefactul nu justifică formalitatea.
Tooling
Câteva unelte care randează C4 bine în 2026.
Mermaid, în-markdown și suportat în majoritatea sistemelor moderne de documentație. Diagramele din lecția asta sunt Mermaid C4. Suportă C4Context, C4Container, C4Component și C4Dynamic. Render-ul e suficient de bun pentru majoritatea utilizărilor, cu margini brute ocazionale în layout. Marele avantaj: diagramele trăiesc în același git repo cu codul, version-controlled și revizuite în pull request-uri.
Structurizr, propria unealtă a lui Brown. Funcționalitatea definitorie e că scrii modelul o singură dată într-un DSL și generezi toate nivelurile C4 din aceeași sursă. Dacă schimbi un container, toate diagramele care îl includ se actualizează automat. Există o versiune găzduită și o imagine Docker self-hosted. E cea mai „C4-nativă” unealtă care există, și dacă urmează să investești profund în C4, merită s-o cunoști.
diagrams.net (anterior draw.io), cu stencil-urile C4 activate. Funcționează bine dacă deja folosești draw.io pentru orice altceva și vrei un editor vizual rapid. Mai puțin riguros decât Structurizr pentru că diagramele sunt desenate manual și modelul nu e impus nicăieri, dar bara de intrare e mai joasă.
PlantUML cu C4-PlantUML. Stabilit de mult timp, bazat pe text, se integrează bine cu toolchain-uri mai vechi. Puțin mai verbos decât Mermaid dar mai bogat în funcționalități în unele privințe. Folosit pe scară largă în setări enterprise care au investit deja în PlantUML pentru sequence diagrams și ERD-uri.
Pentru majoritatea echipelor aș recomanda să începi cu Mermaid pentru diagrame care trăiesc într-un repo de documentație (sweet spot-ul de „version-controlled, revizuibil, ceremonie scăzută”) și să avansezi la Structurizr dacă și când diagramele încep să simtă suficient de mult o entitate încât să le gestionezi ca un model în loc de un set de imagini devine merituos.
Diagramă de creat: Un poster de tip „C4 zoom levels” overview. Patru dreptunghiuri imbricate, fiecare etichetat cu nivelul (1 Context, 2 Container, 3 Component, 4 Code) și un subtitlu scurt (Sistemul în lume, Containerele din interiorul sistemului, Componentele din interiorul unui container, Clasele din interiorul unei componente). În dreapta fiecărui nivel, o etichetă „audiență” pe o linie: business stakeholders, developers și SREs, echipa care construiește containerul, implementatorul componentei. Folosește o culoare consistentă pentru fiecare nivel (sugerat: navy, teal, amber, slate). Titlu sus: „C4 model: four zoom levels for system diagrams.” Atribuirea sursei jos: „After Simon Brown, c4model.com.”
Cu ce ar trebui să rămâi din lecția asta
C4 e o convenție cu patru niveluri de zoom: Context (sistemul în lume), Container (unități deployabile), Component (module din interiorul unui container), Code (rareori desenat). Majoritatea diagramelor utile trăiesc la nivelurile 1 până la 3. Fiecare nivel are o audiență clară și răspunde la o întrebare clară. Cea mai mare victorie practică a folosirii C4 e că conversațiile nu derivă între niveluri de zoom, care e modul de eșec ce produce table ilizibile.
Folosește Mermaid în repository-ul tău de documentație ca cea mai puțin rezistentă cale. Folosește Structurizr dacă vrei o singură sursă de adevăr pentru toate diagramele. Sări peste C4 cu totul pentru sisteme foarte mici, prototipuri foarte timpurii sau diagrame specializate care au propriile convenții.
Lecția următoare, ne mutăm de la desenarea sistemelor la a gândi la ce rulează de fapt sub ele. Lecția 4 se uită la mașina singulară: OS-ul, modelul de proces, threads, async, file I/O și ce poate face o singură cutie înainte să ai nevoie de a doua. Maxima „scale up înainte să scale out” funcționează doar dacă știi ce-ți cumpără efectiv scaling up-ul, și acolo o să mergem.
Referințe
- Simon Brown. The C4 model for visualising software architecture, https://c4model.com (consultat 2026-05-01).
- Simon Brown. Software Architecture for Developers, vol. 2 (2014, cu actualizări în desfășurare).
- Mermaid C4 syntax docs, https://mermaid.js.org/syntax/c4.html (consultat 2026-05-01).
- Structurizr DSL reference, https://docs.structurizr.com/dsl (consultat 2026-05-01).