Platform Standardization

02.07.2026 | Muallif: Jaxongir a.k.a | Kategoriya: Spring Boot | 22 daqiqa o'qish

Platform standardization - kompaniyada yoki katta jamoada Spring Boot projectlarni bitta standart asosida yuritish degani.

Ya’ni har bir team quyidagilarni o‘zi boshidan o‘ylab chiqmaydi:

Logging qanday bo‘ladi?
Security qanday qo‘shiladi?
Tracing qanday ishlaydi?
Exception response formati qanday?
Dependency versionlarni kim boshqaradi?
Project structure qanday bo‘ladi?
Actuator, metrics, health check doim bormi?

Arxitektor darajasida maqsad:

Har bir yangi Spring Boot service bir xil sifat, bir xil structure, bir xil observability, bir xil security va bir xil dependency boshqaruvi bilan boshlansin.

Platform Standardization maqolasi quyidagi qismlardan iborat: internal Spring Boot starter library, centralized security configuration starter, shared observability setup, BOM, project template strategy, va ArchUnit bilan convention enforcement.


1. Nega Platform Standardization kerak?

Katta kompaniyada 10 ta Spring Boot service bo‘lsa, odatda bunday muammo chiqadi:

user-service      → Spring Boot 3.2
payment-service   → Spring Boot 3.1
order-service     → log format boshqa
delivery-service  → security config boshqa
billing-service   → actuator yopiq
catalog-service   → tracing yo‘q
notification      → exception response boshqa

Boshida bu kichik muammo ko‘rinadi. Lekin production’da katta og‘riq beradi:

  • loglarni qidirish qiyinlashadi

  • security xatolar ko‘payadi

  • dependency conflict chiqadi

  • monitoring bir xil bo‘lmaydi

  • yangi service yaratish sekinlashadi

  • har team bir xil muammoni qayta yechadi

  • incident vaqtida tizimni tushunish qiyinlashadi

Platform standardization shuni hal qiladi:

Har service bir xil asosdan boshlanadi.
Har service minimal production talablariga javob beradi.
Har team infrastructure detallarini qayta yozmaydi.

2. Platform team nima qiladi?

Platform team yoki architect team odatda quyidagilarni beradi:

company-spring-boot-starter
company-security-starter
company-observability-starter
company-error-handling-starter
company-bom
company-project-template
architecture-tests
coding conventions

Bu narsalar product teamlarga tayyor beriladi.

Product developer shunchaki dependency qo‘shadi:

<dependency>
    <groupId>com.company.platform</groupId>
    <artifactId>company-web-starter</artifactId>
</dependency>

Va avtomatik keladi:

standard logging
standard error format
standard security headers
standard actuator config
standard tracing
standard metrics
standard correlation-id
standard OpenAPI config

3. Internal Spring Boot Starter Library

Starter nima?

Spring Boot starter - bu bir nechta dependency va configuration’ni bitta package qilib berish usuli.

Spring Boot rasmiy hujjatlarida auto-configuration jar dependency’lar asosida application’ni avtomatik sozlashga harakat qilishi aytiladi. Masalan, classpath’da kerakli kutubxona bo‘lsa va user o‘zi bean bermagan bo‘lsa, Spring Boot kerakli bean’ni auto-config qiladi. (Home)

Custom starter esa kompaniya ichida shunday ishlaydi:

company-security-starter qo‘shildi
        ↓
SecurityFilterChain avtomatik sozlandi
        ↓
JWT decoder avtomatik ulandi
        ↓
public endpointlar standart bo‘ldi
        ↓
security headers qo‘shildi

Spring Boot rasmiy hujjatlarida custom auto-configuration odatda starter bilan bog‘lanishi, starter esa auto-configuration code va kerakli kutubxonalarni birga berishi tushuntirilgan. (Home)


Nega internal starter kerak?

Chunki har projectda shu kodni qayta yozish xato:

@Configuration
public class SecurityConfig {
    // 150 qator security sozlama
}
@Configuration
public class ObservabilityConfig {
    // tracing, metrics, MDC
}
@ControllerAdvice
public class GlobalExceptionHandler {
    // standard error response
}

Yaxshiroq:

<dependency>
    <groupId>com.company.platform</groupId>
    <artifactId>company-service-starter</artifactId>
</dependency>

Va common konfiguratsiya avtomatik ulanadi.


4. Internal starter structure

Masalan:

company-platform
 ├── company-web-starter
 ├── company-security-starter
 ├── company-observability-starter
 ├── company-exception-starter
 ├── company-data-starter
 └── company-bom

Har starter alohida mas’uliyatga ega.

Starter

Vazifasi

company-web-starter

REST convention, Jackson config, CORS, API response

company-security-starter

JWT, OAuth2 resource server, headers, auth rules

company-observability-starter

Micrometer, tracing, logging MDC

company-exception-starter

error response format, global exception handler

company-data-starter

JPA convention, auditing, transaction config

company-test-starter

Testcontainers, WireMock, test utilities


5. Starter ichida auto-configuration

Spring Boot 3.x’da custom auto-configuration odatda shunday yoziladi:

package com.company.platform.web;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
public class CompanyWebAutoConfiguration {

    @Bean
    public CorrelationIdFilter correlationIdFilter() {
        return new CorrelationIdFilter();
    }
}

Keyin AutoConfiguration.imports faylida ro‘yxatdan o‘tkaziladi:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Ichida:

com.company.platform.web.CompanyWebAutoConfiguration

Shunda starter dependency sifatida qo‘shilganda Spring Boot uni avtomatik ko‘radi.


6. @ConditionalOnMissingBean

Internal starter majburlab emas, default berib ishlashi kerak.

Yomon:

@Bean
public ObjectMapper objectMapper() {
    return new ObjectMapper();
}

Bu product team custom ObjectMapper bermoqchi bo‘lsa conflict qiladi.

Yaxshi:

@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
    return new ObjectMapper()
            .findAndRegisterModules();
}

Bu nimani anglatadi?

Agar application o‘z ObjectMapper bean’ini bermagan bo‘lsa,
platform default ObjectMapper beradi.
Agar application o‘zi bergan bo‘lsa,
platform aralashmaydi.

Arxitektor qoida:

Platform default beradi, lekin product teamga override imkonini qoldiradi.


7. Centralized Security Configuration Starter

Security har service’da boshqacha yozilsa, xavf oshadi.

Masalan, bitta service’da:

.requestMatchers("/actuator/**").permitAll()

boshqasida:

.anyRequest().permitAll()

boshqasida CSRF noto‘g‘ri disable qilingan.

Bunday holatda production’da security incident bo‘lishi oson.


company-security-starter

Bu starter quyidagilarni standart qiladi:

JWT validation
OAuth2 Resource Server config
public endpoint convention
role/scope mapping
security headers
CORS policy
actuator endpoint security
method security
audit logging

Misol:

@AutoConfiguration
@EnableMethodSecurity
public class CompanySecurityAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/actuator/health", "/actuator/info").permitAll()
                        .requestMatchers("/api/public/**").permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth -> oauth.jwt())
                .build();
    }
}

Bu bilan har service default secure bo‘ladi.


Security starter’da ehtiyot bo‘lish kerak

Platform security starter haddan tashqari qattiq bo‘lsa, teamlar uni chetlab o‘tadi.

Yaxshi starter:

secure default beradi
override qilishga ruxsat beradi
config property orqali sozlanadi
documentation bor
test utilities beradi

Masalan:

company:
  security:
    public-paths:
      - /api/public/**
      - /swagger-ui/**
    required-scope: orders.read

8. Shared Observability Setup

Observability - production’da systemni ko‘ra olish:

logs
metrics
traces
health checks
alerts
correlation-id

Har service’da observability bir xil bo‘lishi kerak.


company-observability-starter

Bu starter quyidagilarni beradi:

Actuator endpoints
Micrometer metrics
Prometheus registry
traceId/spanId logging
correlation-id filter
structured logging
custom business metrics
health indicators

Misol:

Request keldi
        ↓
CorrelationIdFilter correlation-id yaratdi
        ↓
MDC ichiga qo‘ydi
        ↓
Loglarda correlationId chiqdi
        ↓
Trace systemga yuborildi
        ↓
Prometheus metrics yig‘di

Log formati hamma service’da bir xil bo‘lsa, incident vaqtida juda katta foyda beradi.


Standard log format

Masalan:

{
  "timestamp": "2026-05-21T10:15:00Z",
  "level": "INFO",
  "service": "order-service",
  "traceId": "abc123",
  "spanId": "def456",
  "correlationId": "req-789",
  "message": "Order created"
}

Bu format har service’da bir xil bo‘lsa:

Kibana / Grafana Loki / Datadog’da qidirish oson bo‘ladi.
Trace bilan log bog‘lanadi.
Incident debugging tezlashadi.

9. Standard Error Handling Starter

Har service xatoni har xil qaytarsa, frontend va boshqa service’lar qiynaladi.

Yomon:

{
  "error": "Bad request"
}

Boshqa service:

{
  "message": "Validation failed",
  "code": 400
}

Boshqa service:

{
  "timestamp": "...",
  "status": 400,
  "path": "/orders"
}

Yaxshi standart:

{
  "type": "VALIDATION_ERROR",
  "message": "Validation failed",
  "traceId": "abc123",
  "details": [
    {
      "field": "email",
      "message": "must be a valid email"
    }
  ]
}

Global exception starter

@RestControllerAdvice
public class CompanyExceptionHandler {

    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ApiError> handleValidation(ValidationException ex) {
        return ResponseEntity.badRequest().body(
                ApiError.validation(ex.getMessage())
        );
    }

    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ApiError> handleNotFound(EntityNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(
                ApiError.notFound(ex.getMessage())
        );
    }
}

Buni har service’da qayta yozish kerak emas. Starter beradi.


10. BOM - Bill of Materials

BOM nima?

BOM - dependency versionlarni markazdan boshqarish.

Masalan, har project o‘zi yozsa:

<spring.boot.version>3.3.1</spring.boot.version>
<spring.cloud.version>2023.0.2</spring.cloud.version>
<mapstruct.version>1.5.5</mapstruct.version>
<testcontainers.version>1.19.8</testcontainers.version>

Bitta projectda boshqa, ikkinchisida boshqa bo‘lib ketadi.

BOM bilan:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.company.platform</groupId>
            <artifactId>company-bom</artifactId>
            <version>1.4.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Keyin dependency version yozilmaydi:

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
</dependency>

Spring Boot Gradle plugin hujjatlarida dependency’larni boshqarish uchun io.spring.dependency-management plugin yoki Gradle native BOM support ishlatilishi mumkinligi aytilgan. (Home) Gradle rasmiy hujjatlarida BOM dependency version constraints’larni markaziy boshqarish uchun ishlatilishi ko‘rsatilgan. (Gradle Documentation)


Company BOM ichida nima bo‘ladi?

Spring Boot version
Spring Cloud version
Spring Modulith version
MapStruct version
Testcontainers version
OpenAPI version
Micrometer version
Resilience4j version
Kafka client version
PostgreSQL driver version

Foydasi:

dependency conflict kamayadi
upgrade markazdan qilinadi
CVE patch qilish osonlashadi
teamlar version tanlashga vaqt sarflamaydi
build reproducible bo‘ladi

11. Project Template Strategy

Har yangi service noldan yaratilmasligi kerak.

Yomon:

Developer start.spring.io ga kiradi
dependencylarni taxminan tanlaydi
package structure o‘zi qiladi
security keyin qo‘shiladi
observability esdan chiqadi

Yaxshi:

company project template ishlatiladi
default package structure bor
starterlar tayyor
CI/CD pipeline bor
Dockerfile bor
Actuator bor
test skeleton bor
README bor

Spring Initializr rasmiy hujjatlarida o‘z custom Initializr instance’ingizni yaratish, dependencylar ro‘yxati va project attribute constraints’larni sozlash mumkinligi aytilgan. (Home)


Template ichida nima bo‘lishi kerak?

src/main/java/com/company/service
 ├── ServiceApplication.java
 ├── config
 ├── common
 ├── module1
 └── module2

src/test/java
 ├── ArchitectureTest.java
 ├── IntegrationTestBase.java
 └── TestcontainersConfig.java

Dockerfile
docker-compose.yml
README.md
openapi.yml
.github/workflows/build.yml yoki .gitlab-ci.yml

Minimum production template:

Health check
Readiness/liveness
Structured logging
Security default
Exception format
OpenAPI config
Testcontainers setup
Architecture test
Docker build
CI quality gates

12. Archetype yoki Custom Initializr?

Maven Archetype

Oddiy project skeleton yaratish uchun ishlatiladi.

Foydasi:

sodda
tez
ichki template uchun yetarli

Kamchiligi:

dynamic dependency tanlash qiyinroq
UI yo‘q
enterprise customization cheklangan

Custom Spring Initializr

Katta platform uchun kuchliroq.

Foydasi:

ichki start.company.com qilish mumkin
team dependency tanlaydi
Java version constraint beriladi
Spring Boot version nazorat qilinadi
company starterlar default chiqadi

Masalan:

start.company.uz
 ├── Web API Service
 ├── Kafka Consumer Service
 ├── Batch Job
 ├── Modulith Application
 └── Library Project

Arxitektor qaror:

Kichik kompaniyada template yetadi. Katta kompaniyada custom Initializr yoki internal developer portal foydaliroq.


13. Enforcing Conventions - ArchUnit Tests

Documentation yetarli emas. Qoidalar test bilan tekshirilishi kerak.

ArchUnit user guide’da architecture qoidalarini concise syntax bilan yozish va layered architecture kabi tayyor qoidalar mavjudligi ko‘rsatilgan. (ArchUnit)


Misol: Controller repository chaqirmasin

@AnalyzeClasses(packages = "com.company")
class ArchitectureTest {

    @ArchTest
    static final ArchRule controllers_should_not_access_repositories =
            noClasses()
                    .that().resideInAPackage("..controller..")
                    .should().accessClassesThat()
                    .resideInAPackage("..repository..");
}

Bu nimani himoya qiladi?

Controller → Service → Repository tartibini

Misol: internal package tashqaridan ishlatilmasin

@ArchTest
static final ArchRule internal_packages_should_not_be_accessed =
        noClasses()
                .that().resideOutsideOfPackage("..order..")
                .should().accessClassesThat()
                .resideInAPackage("..order.internal..");

Bu modular architecture’ni himoya qiladi.


Misol: Service classlar @Transactional bilan ishlasin

@ArchTest
static final ArchRule services_should_be_transactional =
        classes()
                .that().resideInAPackage("..application..")
                .and().haveSimpleNameEndingWith("Service")
                .should().beAnnotatedWith(Transactional.class);

Ehtiyot bo‘lish kerak: bunday qoida hamma project uchun mos bo‘lmasligi mumkin. Shuning uchun platform convention aniq yozilishi kerak.


14. Standard Package Structure

Platform team quyidagi structure’ni majburlashi mumkin:

com.company.<service>
 ├── <domain-module>
 │    ├── api
 │    ├── application
 │    ├── domain
 │    ├── adapter
 │    │    ├── in
 │    │    │    └── web
 │    │    └── out
 │    │         ├── persistence
 │    │         └── messaging
 │    └── internal
 │
 ├── config
 └── ServiceApplication.java

Yoki sodda service uchun:

com.company.<service>
 ├── controller
 ├── service
 ├── repository
 ├── dto
 ├── config
 └── exception

Arxitektor muhim qaror qiladi:

Hamma service’ga bir xil murakkab architecture tiqilmaydi. Service turiga qarab template bo‘ladi.


15. Service Type bo‘yicha standartlar

Service turi

Tavsiya structure

Simple CRUD

Layered architecture

Business-heavy service

Hexagonal + DDD

Katta monolith

Spring Modulith

Kafka consumer

Message-driven template

Batch job

Spring Batch template

API Gateway

Gateway-specific template

Library

Starter/library template

Bu juda muhim. Chunki platform standardization degani bitta qolipni hammaga majburlash emas.


16. Versioning Strategy

Platform starterlar ham versionlanadi.

Masalan:

company-platform-bom: 1.0.0
company-platform-bom: 1.1.0
company-platform-bom: 2.0.0

Semantic versioning:

PATCH 1.0.1 → bug fix
MINOR 1.1.0 → backward compatible feature
MAJOR 2.0.0 → breaking change

Product service company-bom versionini yangilaydi:

<company.platform.version>1.4.0</company.platform.version>

Va barcha common dependencylar boshqariladi.


17. Platform upgrade process

Yaxshi platform team shunday ishlaydi:

1. Yangi Spring Boot version chiqadi
2. Platform team compatibility tekshiradi
3. company-bom update qilinadi
4. starterlar test qilinadi
5. migration guide yoziladi
6. sample service yangilanadi
7. product teamlarga upgrade PR ochiladi

Bu Spring Boot upgrade’ni har team alohida boshdan o‘tkazmasligini ta’minlaydi.


18. Security patch va CVE boshqaruvi

Agar har service dependency versionni o‘zi boshqarsa:

Log4j / Netty / Jackson / Tomcat CVE chiqsa,
qaysi service qaysi versionda ekanini topish qiyin.

BOM bilan:

company-bom update qilinadi
barcha service bir xil patched versionga o‘tadi
CI tekshiradi

Platform standardization production xavfsizlik uchun ham kerak.


19. Developer Experience - DX

Platform standardization faqat control emas. Developer hayotini osonlashtirishi kerak.

Yomon platform:

ko‘p qoida
kam dokumentatsiya
override qiyin
starterlar magic qiladi
xato chiqqanda tushunarsiz

Yaxshi platform:

tez project yaratadi
defaultlar xavfsiz
documentation aniq
sample project bor
starterlar override bo‘ladi
error message tushunarli
migration guide bor

Arxitektor uchun muhim savol:

Platform team product teamlarga yordam beryaptimi yoki faqat cheklov qo‘yyaptimi?


20. Real kompaniya misoli

Tasavvur qilamiz, sizda 20 ta Spring Boot service bor.

Platform standardization oldin:

Har service boshqa log format.
Security config har xil.
Exception response har xil.
Actuator ba’zilarida ochiq, ba’zilarida yopiq.
Dependency versionlar chalkash.
Yangi service yaratish 2-3 kun.

Platform standardization keyin:

Yangi service 15 daqiqada template’dan yaratiladi.
Security default tayyor.
Observability default tayyor.
Error response bir xil.
Dependencylar BOM orqali boshqariladi.
Architecture testlar bor.
CI pipeline standart.

Bu Arxitektor darajasidagi katta yutuq.


21. Minimal platform starter misoli

Auto-configuration

@AutoConfiguration
@EnableConfigurationProperties(CompanyProperties.class)
public class CompanyPlatformAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public CorrelationIdFilter correlationIdFilter() {
        return new CorrelationIdFilter();
    }

    @Bean
    @ConditionalOnMissingBean
    public ApiErrorFactory apiErrorFactory() {
        return new ApiErrorFactory();
    }
}

Properties

@ConfigurationProperties(prefix = "company.platform")
public record CompanyProperties(
        boolean correlationIdEnabled,
        String serviceName
) {}

application.yml

company:
  platform:
    correlation-id-enabled: true
    service-name: order-service

Bu starter barcha service’larda bir xil correlation-id va error handling beradi.


22. Platform standardization’da nimalarni majburlash kerak?

Majburiy bo‘lishi kerak

dependency BOM
security baseline
structured logging
health/readiness endpoint
metrics
trace-id/correlation-id
standard error response
CI quality checks
architecture tests
Docker/build standard

Tavsiya bo‘lishi mumkin

package structure
Hexagonal architecture
CQRS
Spring Modulith
specific mapper library
specific HTTP client style

Majburlamaslik kerak

hamma service’da bir xil murakkab architecture
keraksiz abstraction
ortiqcha custom framework
teamga mos kelmaydigan pattern

23. Eng ko‘p xatolar

Xato 1: Platform starter juda ko‘p magic qiladi

Developer nima bo‘layotganini tushunmaydi.

Yaxshi starter:

default beradi
log qiladi
override imkon beradi
documentation beradi

Xato 2: Product team ehtiyojini eshitmaslik

Platform team:

"Biz shunday dedik, shunday bo‘ladi."

desa, teamlar workaround qiladi.

To‘g‘ri yondashuv:

Platform product sifatida yuritiladi.
Developerlar uning foydalanuvchisi.

Xato 3: BOM update qilinmaydi

BOM bor, lekin eskirib qolsa, foydasi kamayadi.

Platform team doim:

Spring Boot update
security patch
dependency compatibility
CVE monitoring

qilishi kerak.


Xato 4: Convention faqat dokumentatsiyada qoladi

Dokumentatsiya yaxshi, lekin test bo‘lmasa qoida buziladi.

Yaxshi:

README + template + ArchUnit + CI

Xato 5: Hamma narsani common library’ga tashlash

common library haddan tashqari kattalashib ketadi:

common-utils
common-domain
common-service
common-repository

Natija:

hamma service common’ga qaram
version upgrade xavfli
domainlar aralashadi

Qoida:

Common library faqat haqiqatan umumiy infrastructure narsalar uchun. Business logic common’ga chiqmasin.


24. Amaliy roadmap

Platform standardization’ni bosqichma-bosqich qilish:

1. Hozirgi service’larni audit qilish
2. Umumiy muammolarni topish
3. Minimal company-bom yaratish
4. company-observability-starter yaratish
5. company-security-starter yaratish
6. standard error handling starter qo‘shish
7. project template yaratish
8. ArchUnit architecture tests qo‘shish
9. CI pipeline standard qilish
10. migration guide yozish

Birdan hammasini qilish shart emas. Avval eng ko‘p takrorlanadigan va eng xavfli joylardan boshlanadi:

Security
Observability
Dependency management
Error handling

25. Arxitektor xulosasi

Platform standardization - Spring Boot projectlar soni ko‘payganda majburiy darajaga chiqadigan architecture mavzu.

Asosiy g‘oya:

Har team bir xil infrastructure muammolarini qayta yechmasin.
Har service production-ready default bilan boshlansin.
Dependency, security, logging, monitoring va structure markazdan boshqarilsin.
Lekin product teamlar kerak joyda override qila olsin.

Eng muhim qoida:

Platform standardization control uchun emas, tezlik va sifat uchun qilinadi.

Yaxshi platform developerga shuni beradi:

kamroq boilerplate
kamroq xato
tezroq start
osonroq monitoring
xavfsizroq default
osonroq upgrade