Arxitektura qarorlari bayonnomasi (Architecture Decision Records)

30.06.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Architecture | 16 daqiqa o'qish

Oldingi mavzuda Architecture styles ko‘rgan edik. Endi arxitektor uchun juda muhim amaliy mavzu:

Architecture Decision Records - ADR

Bu mavzu ichida quyidagilar bor: ADR format & lifecycle, trade-off analysis, fitness functions, architecture governance, tech radar.


1. ADR nima?

ADR - Architecture Decision Record

Ya’ni:

Muhim texnik qaror nima uchun qabul qilinganini yozib qo‘yadigan qisqa hujjat.

Masalan:

  • Nega monolith tanladik?

  • Nega PostgreSQL ishlatyapmiz?

  • Nega Kafka emas, RabbitMQ?

  • Nega REST emas, gRPC?

  • Nega Redis cache qo‘shildi?

  • Nega modular monolithdan microservicesga o‘tyapmiz?

  • Nega Spring Boot tanlandi?

ADR kod emas. Lekin u koddan ham muhim bo‘lishi mumkin, chunki u qarorning sababini saqlaydi.


2. Nega ADR kerak?

Ko‘p loyihalarda shunday bo‘ladi:

Developer: Nega bu yerda Kafka ishlatilgan?
Teamlead: Bilmayman, men kelganimda bor edi.
Arxitektor: Oldin bir sabab bo‘lgan, lekin hech kim eslamaydi.

Bu yomon holat.

ADR bo‘lsa, yangi odam kelib o‘qiydi:

ADR-004: Use RabbitMQ for order notifications

Status: Accepted
Date: 2026-03-12

Context:
Order yaratilganda SMS, email, push notification yuborish kerak.
Bu jarayon order yaratishni sekinlashtirmasligi kerak.

Decision:
RabbitMQ ishlatamiz.

Reason:
Routing murakkab emas, latency past, team RabbitMQ bilan ishlagan.
Kafka bu holat uchun ortiqcha complexity beradi.

Consequences:
Notification async bo‘ladi.
Agar RabbitMQ vaqtincha ishlamasa, retry va DLQ kerak.

Endi hamma sababni tushunadi.


3. ADR qachon yoziladi?

Har bir kichik qarorga ADR kerak emas.

ADR kerak bo‘ladigan qarorlar

Qaror turi

Misol

Architecture style

Modular monolith tanlash

Database tanlash

PostgreSQL vs MongoDB

Messaging tanlash

Kafka vs RabbitMQ

API style

REST vs gRPC vs GraphQL

Security approach

JWT vs Session

Deployment strategy

Kubernetes vs VM

Cache strategy

Redis qo‘shish

Data consistency

SAGA tanlash

Framework/library

Spring Cloud Gateway ishlatish


ADR kerak bo‘lmaydigan holatlar

Bular uchun odatda ADR shart emas:

  • method nomini o‘zgartirish;

  • bitta class refactor qilish;

  • kichik bug fix;

  • oddiy dependency version update;

  • bitta endpoint path nomi;

  • UI rangini o‘zgartirish.

Qoida:

Qaror keyingi 6-24 oy davomida sistemaga ta’sir qilsa - ADR yozish kerak.


4. ADR formati

ADR juda katta document bo‘lishi shart emas. 1-2 sahifa yetadi.

Eng oddiy format:

# ADR-001: Use Modular Monolith

## Status
Accepted

## Date
2026-05-20

## Context
Biz e-commerce backend qurmoqdamiz.
Team kichik: 5 developer.
Domain hali tez o‘zgaradi.
Mustaqil deploy hozircha shart emas.

## Decision
Boshida modular monolith architecture tanlaymiz.

## Alternatives Considered
1. Traditional monolith
2. Microservices
3. Modular monolith

## Consequences
Positive:
- Development tezroq bo‘ladi.
- Deployment oddiy.
- Modul chegaralari keyinchalik microservicesga ajratishga yordam beradi.

Negative:
- Hamma modul bitta app sifatida deploy qilinadi.
- Developerlar modul chegarasini buzmasligi uchun code review kerak.

## Review Date
2026-11-20

5. ADR statuslari

ADR lifecycle’da status muhim.

Status

Ma’nosi

Proposed

Taklif qilingan, hali qabul qilinmagan

Accepted

Qabul qilingan qaror

Rejected

Rad qilingan

Deprecated

Endi tavsiya qilinmaydi

Superseded

Yangi ADR bilan almashtirilgan


Misol

ADR-002: Use MongoDB for Orders
Status: Rejected

Nega rejected ADR ham saqlanadi?

Chunki 6 oy keyin yana kimdir:

"Orders uchun MongoDB ishlatsak bo‘lmaydimi?"

desa, javob tayyor bo‘ladi:

Bu variant ko‘rib chiqilgan.
Sabablari bilan rad qilingan.

Bu team vaqtini tejaydi.


6. ADR lifecycle

ADR hayoti odatda shunday:

Problem paydo bo‘ladi
        ↓
Variantlar yoziladi
        ↓
Trade-off tahlil qilinadi
        ↓
Qaror qabul qilinadi
        ↓
ADR accepted bo‘ladi
        ↓
Amalda ishlatiladi
        ↓
Vaqti-vaqti bilan qayta ko‘riladi
        ↓
Kerak bo‘lsa deprecated/superseded qilinadi

7. Trade-off analysis

Arxitektor qaror qabul qilganda "bu yaxshi, bu yomon" demaydi.

U shunday o‘ylaydi:

Har bir tanlov nimanidir beradi, nimanidir olib qo‘yadi.

Bu trade-off deyiladi.


Misol: Kafka vs RabbitMQ

Mezon

Kafka

RabbitMQ

Throughput

Juda yuqori

O‘rtacha/yaxshi

Routing

Oddiyroq

Juda kuchli

Message retention

Kuchli

Asosan queue modeli

Learning curve

Qiyinroq

Osonroq

Replay

Juda yaxshi

Tabiiy emas

Use case

Event streaming

Task queue / routing

Arxitektor xulosasi:

Agar event streaming, replay, audit kerak bo‘lsa → Kafka.
Agar task queue, notification, routing kerak bo‘lsa → RabbitMQ.

Misol ADR

# ADR-005: Use RabbitMQ for Notification Delivery

## Status
Accepted

## Context
Order yaratilganda SMS, Telegram, Push, Email notification yuboriladi.
Har notification turi turli service tomonidan qayta ishlanadi.
Bizga murakkab routing va retry kerak.
Event replay hozircha kerak emas.

## Decision
RabbitMQ ishlatamiz.

## Alternatives Considered
1. Kafka
2. RabbitMQ
3. Direct synchronous HTTP calls

## Trade-offs
RabbitMQ:
+ Routing uchun qulay
+ Team tajribasi bor
+ DLQ va retry oson
- Event replay Kafka kabi kuchli emas

Kafka:
+ High throughput
+ Replay imkoniyati kuchli
- Hozirgi case uchun complexity ortiqcha

HTTP calls:
+ Oddiy
- Order yaratish sekinlashadi
- Notification service yiqilsa order flow ta’sirlanadi

## Consequences
Notification async ishlaydi.
RabbitMQ monitoring va DLQ handling majburiy bo‘ladi.

8. Fitness Functions

Fitness function nima?

Architecture’da fitness function - architecture qarori ishlayotganini avtomatik yoki yarim avtomatik tekshiradigan qoida.

Oddiy qilib:

"Biz tanlagan architecture vaqt o‘tib buzilmayaptimi?"


Misol: Modular Monolith

Biz ADR’da shunday qaror qildik:

Order module Product module’ning repositorysini to‘g‘ridan-to‘g‘ri chaqirmasin.

Fitness function:

Order package ichida product.infrastructure package import qilinmasin.

Buni test bilan tekshirish mumkin.

Java’da ArchUnit bilan:

@Test
void orderShouldNotAccessProductInfrastructure() {
    noClasses()
        .that().resideInAPackage("..order..")
        .should().accessClassesThat()
        .resideInAPackage("..product.infrastructure..")
        .check(importedClasses);
}

Bu test CI’da yursa, architecture buzilishi build’da ko‘rinadi.


Boshqa fitness function misollari

Architecture qarori

Fitness function

Controller domain entity qaytarmasin

REST response faqat DTO bo‘lsin

Service layer repositorysiz ishlamasin

Controller repository chaqirmasin

Module boundary saqlansin

Cross-module importlar nazorat qilinsin

API latency 300ms’dan oshmasin

Performance test / metric alert

Service stateless bo‘lsin

Local file/session ishlatilmasin

Security majburiy bo‘lsin

Public endpointlar ro‘yxati tekshirilsin


9. Architecture Governance

Governance nima?

Architecture governance - teamlar architecture qoidalariga amal qilishini boshqarish.

Bu "arxitektor hammani majburlaydi" degani emas.

To‘g‘ri governance:

Qarorlar aniq
Sabablar yozilgan
Qoidalar avtomatlashtirilgan
Istisnolar muhokama qilinadi
Teamlar tushunadi

Yomon governance

Arxitektor: Bunday qilmang.
Developer: Nega?
Arxitektor: Chunki men shunday dedim.

Bu ishlamaydi.


Yaxshi governance

Arxitektor: Biz ADR-003'da module boundary qoidasini qabul qilganmiz.
Sababi: payment logic order ichiga aralashib ketmasligi kerak.
ArchUnit test ham shuni tekshiradi.
Agar exception kerak bo‘lsa, yangi ADR yoki amendment qilamiz.

Bu sog‘lom yondashuv.


10. Tech Radar

Tech Radar nima?

Tech Radar - kompaniya yoki team qaysi texnologiyalarni ishlatishi, sinashi yoki tark etishini ko‘rsatadigan xarita.

Odatda 4 kategoriya bo‘ladi:

Kategoriya

Ma’nosi

Adopt

Ishlatishga tavsiya qilinadi

Trial

Sinab ko‘rish mumkin

Assess

O‘rganish kerak

Hold

Hozircha ishlatmaslik kerak


Java team uchun misol Tech Radar

Texnologiya

Status

Sabab

Java 21

Adopt

LTS, virtual threads mavjud

Spring Boot 3.x

Adopt

Production-ready stack

PostgreSQL

Adopt

Ishonchli relational DB

Redis

Adopt

Cache va distributed lock uchun

Kafka

Trial

Streaming case’lar uchun

RabbitMQ

Adopt

Queue/routing uchun

GraphQL

Assess

Ayrim frontend-heavy case’lar uchun

MongoDB

Trial

Document-heavy domain bo‘lsa

Custom framework

Hold

Maintenance xavfi katta


11. ADR qayerda saqlanadi?

Eng yaxshi joy - project repository ichida.

project-root
 ├── src
 ├── docs
 │    └── adr
 │         ├── 0001-use-modular-monolith.md
 │         ├── 0002-use-postgresql.md
 │         ├── 0003-use-rabbitmq.md
 │         └── 0004-use-redis-cache.md
 └── README.md

Nega repository ichida?

  • code bilan birga versionlanadi;

  • pull request’da review qilinadi;

  • tarix Git’da qoladi;

  • yangi developer osongina topadi.


12. ADR yozishda eng katta xatolar

1. Juda uzun yozish

ADR 20 sahifa bo‘lsa, hech kim o‘qimaydi.

Yaxshi ADR:

1-2 sahifa
aniq sabab
aniq qaror
aniq consequence

2. Faqat qarorni yozish, sababni yozmaslik

Yomon:

We use Kafka.

Yaxshi:

We use Kafka because we need event replay, high throughput,
and event streaming as integration backbone.

3. Alternative variantlarni yozmaslik

Qaror kuchli bo‘lishi uchun boshqa variantlar ham ko‘rsatilishi kerak.

Considered:
- Kafka
- RabbitMQ
- PostgreSQL LISTEN/NOTIFY
- Direct HTTP calls

4. Negative consequence yozmaslik

Har qarorning minuslari bor.

Agar ADR faqat pluslardan iborat bo‘lsa, bu marketing document bo‘lib qoladi.

Yaxshi ADR minuslarni ham aytadi:

Negative:
- Kafka operation complexity oshadi.
- Schema evolution boshqarilishi kerak.
- Local development murakkablashadi.

13. Real Spring Boot loyiha uchun ADR namunasi

# ADR-001: Use Modular Monolith for Initial Architecture

## Status
Accepted

## Date
2026-05-20

## Context
We are building a sales management system with two Android apps:
Supervisor app and Sales Agent app.

The backend includes:
- authentication
- agent management
- customer management
- visit tracking
- order collection
- reporting

The team is small.
The domain is still evolving.
Independent service deployment is not required yet.

## Decision
We will start with a modular monolith architecture using Spring Boot.

Modules:
- auth
- agents
- customers
- visits
- orders
- reports
- notifications

Each module must expose public application services or facades.
Direct access to another module's repository or internal package is not allowed.

## Alternatives Considered

### Traditional Monolith
Pros:
- fastest to start
- simple deployment

Cons:
- boundaries will likely become unclear
- future extraction will be harder

### Microservices
Pros:
- independent deployment
- independent scaling

Cons:
- too much operational complexity for current team size
- distributed transactions and observability are not ready yet
- domain boundaries are not stable

### Modular Monolith
Pros:
- simple deployment
- clear module boundaries
- easier future extraction to microservices

Cons:
- requires discipline
- all modules are still deployed together

## Consequences

Positive:
- Faster development
- Easier local debugging
- Clear business modules
- Lower infrastructure complexity

Negative:
- Cannot deploy modules independently
- Requires architecture tests and code review discipline

## Fitness Functions
- No module can access another module's infrastructure package.
- Controllers must not access repositories directly.
- All inter-module communication must go through public facades or ports.

## Review Date
2026-11-20

14. Arxitektor uchun asosiy qoida

ADR yozishdan maqsad "hujjat ko‘paytirish" emas.

Maqsad:

Qaror yo‘qolmasin.
Sabab unutilmasin.
Team bir xil tushunsin.
Yangi odam tez moslashsin.
Kelajakda noto‘g‘ri qayta qaror qilinmasin.

15. Qisqa formula

ADR = Decision + Context + Alternatives + Consequences

Yana qisqaroq:

Nima tanladik, nega tanladik, nimalardan voz kechdik, endi qanday oqibat bo‘ladi?


Yakuniy xulosa

Architecture Decision Records arxitektor uchun juda amaliy qurol.

U quyidagilarni beradi:

  • qarorlar tarixini saqlaydi;

  • team alignment yaratadi;

  • yangi developerga context beradi;

  • "nega bunday qilingan?" savoliga javob beradi;

  • architecture drift’ni kamaytiradi;

  • kelajakdagi refactor va migration’ni osonlashtiradi.

Arxitektor darajasida yaxshi savol bu emas:

"Qaysi texnologiya zo‘r?"

Yaxshi savol:

"Biz bu qarorni qaysi contextda, qaysi trade-offlar bilan qabul qilyapmiz va buni keyinchalik qanday tekshiramiz?"