Full Stack • Java • System Design • Cloud • AI Engineering

Clean Architecture

Learn Clean Architecture from the ground up. Understand the Dependency Rule, Layers, Domain Model, Use Cases, Adapters, Frameworks, SOLID principles, Spring Boot implementation, Hexagonal Architecture comparison, and real-world enterprise examples from Banking, Amazon, Netflix, Uber, and Microservices.


Introduction

Imagine you're building an Online Banking Application.

The application supports:

  • Customer Registration
  • Account Management
  • Money Transfer
  • Loan Processing
  • Credit Cards
  • Notifications

Initially, everything is implemented inside controllers.

@RestController
public class TransferController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @PostMapping("/transfer")
    public String transfer() {

        // Validation

        // Business Logic

        // SQL Query

        // Notification

        return "Success";
    }
}

Everything is mixed together.

Problems appear quickly:

  • ❌ Difficult to test
  • ❌ Tight coupling
  • ❌ Business logic depends on Spring Boot
  • ❌ Database changes affect business rules
  • ❌ Hard to migrate technologies
  • ❌ Low maintainability

Modern enterprise systems solve this using Clean Architecture.


Learning Objectives

After completing this article, you'll understand:

  • What is Clean Architecture?
  • Why Clean Architecture?
  • Dependency Rule
  • Four Layers
  • Entities
  • Use Cases
  • Interface Adapters
  • Frameworks & Drivers
  • Dependency Injection
  • SOLID Principles
  • Spring Boot Implementation
  • Comparison with Layered Architecture
  • Hexagonal Architecture
  • Best Practices

What is Clean Architecture?

Clean Architecture is an architectural pattern proposed by Robert C. Martin (Uncle Bob).

Its primary goal is:

Business Rules should not depend on frameworks, databases, or external technologies.

Instead,

everything depends towards the center.


Traditional Layered Architecture

flowchart TD

CLIENT[Client]

CONTROLLER[Controller]

SERVICE[Service]

REPOSITORY[Repository]

DATABASE[(Database)]

CLIENT --> CONTROLLER
CONTROLLER --> SERVICE
SERVICE --> REPOSITORY
REPOSITORY --> DATABASE

The business layer often becomes tightly coupled to Spring Boot and JPA.


Clean Architecture

flowchart TD

FRAMEWORK[Frameworks & Drivers]

ADAPTERS[Interface Adapters]

USECASE[Use Cases]

ENTITY[Entities]

FRAMEWORK --> ADAPTERS
ADAPTERS --> USECASE
USECASE --> ENTITY

Dependencies always point inward.


The Dependency Rule

The most important rule.

Outer Layers

↓

Depend On

↓

Inner Layers

Never the opposite.

The Domain must never know:

  • Spring Boot
  • Hibernate
  • PostgreSQL
  • Kafka
  • REST
  • Redis

Core Layers

flowchart LR

E[Entities]

UC[Use Cases]

IA[Interface Adapters]

FW[Frameworks]

FW --> IA
IA --> UC
UC --> E

Layer 1 — Entities

The center of the architecture.

Contains

  • Business Rules
  • Domain Models
  • Validation
  • Business Policies

Example

public class Account {

    private BigDecimal balance;

    public void withdraw(BigDecimal amount){

        if(balance.compareTo(amount) < 0){
            throw new RuntimeException("Insufficient Balance");
        }

        balance = balance.subtract(amount);
    }
}

Notice

No Spring annotations.

No JPA annotations.

Pure Java.


Why Entities Should Be Independent?

Entities should survive even if tomorrow you replace:

  • Spring Boot → Micronaut
  • PostgreSQL → MongoDB
  • REST → GraphQL

Business logic remains unchanged.


Layer 2 — Use Cases

Use Cases contain

Application Business Logic.

Example

Transfer Money

↓

Validate Account

↓

Withdraw

↓

Deposit

↓

Save

Use Case Flow

flowchart TD

REQUEST[Transfer Request]

VALIDATE[Validate]

WITHDRAW[Withdraw Money]

DEPOSIT[Deposit Money]

SAVE[Persist]

REQUEST --> VALIDATE
VALIDATE --> WITHDRAW
WITHDRAW --> DEPOSIT
DEPOSIT --> SAVE

Example Use Case

public class TransferMoneyUseCase {

    private AccountRepository repository;

    public void execute(TransferRequest request){

        // Business Logic

    }

}

Notice

No Spring Boot annotations.

No REST.


Layer 3 — Interface Adapters

Adapters convert external requests into use cases.

Examples

  • REST Controllers
  • GraphQL
  • Kafka Consumers
  • JPA Repositories
  • DTO Mappers

Adapter Flow

flowchart LR

REST[REST Controller]

DTO[DTO Mapper]

USECASE[Use Case]

REST --> DTO
DTO --> USECASE

REST Controller

@RestController
public class TransferController {

    @PostMapping("/transfer")
    public ResponseEntity<?> transfer(){

        useCase.execute();

        return ResponseEntity.ok().build();

    }

}

Controller only delegates.

Business logic stays in Use Cases.


Repository Interface

Inside the Domain

public interface AccountRepository{

    void save(Account account);

    Account find(Long id);

}

The domain defines the contract.


Repository Implementation

Infrastructure Layer

@Repository
public class JpaAccountRepository
implements AccountRepository{

}

JPA is hidden behind the interface.


Layer 4 — Frameworks & Drivers

Outer layer.

Contains

  • Spring Boot
  • Hibernate
  • PostgreSQL
  • Kafka
  • Redis
  • REST APIs
  • AWS SDK

These are implementation details.


Complete Request Flow

sequenceDiagram

participant Client
participant Controller
participant UseCase
participant Repository
participant Database

Client->>Controller: POST /transfer

Controller->>UseCase: execute()

UseCase->>Repository: save()

Repository->>Database: INSERT

Database-->>Repository: Success

Repository-->>UseCase: Saved

UseCase-->>Controller: Success

Controller-->>Client: 200 OK

Dependency Injection

Spring Boot wires dependencies.

flowchart LR

SPRING[Spring Container]

CONTROLLER[Controller]

USECASE[Use Case]

REPOSITORY[Repository]

SPRING --> CONTROLLER
SPRING --> USECASE
SPRING --> REPOSITORY

Business logic remains framework independent.


Spring Boot Folder Structure

src

├── domain
│     ├── entity
│     ├── repository
│     └── usecase
│
├── application
│
├── infrastructure
│     ├── persistence
│     ├── kafka
│     ├── redis
│     └── security
│
├── web
│     ├── controller
│     └── dto
│
└── config

Example Banking Architecture

flowchart TD

CLIENT[Customer]

API[REST API]

USECASE[Transfer Money]

DOMAIN[Account Entity]

JPA[JPA Repository]

DB[(PostgreSQL)]

CLIENT --> API
API --> USECASE
USECASE --> DOMAIN
USECASE --> JPA
JPA --> DB

Clean Architecture vs Layered Architecture

Layered Clean
Framework-centric Domain-centric
Business depends on Spring Spring depends on Business
Difficult to replace DB Easy to replace DB
Lower Testability High Testability
Tighter Coupling Loose Coupling

Clean Architecture vs Hexagonal Architecture

Clean Architecture Hexagonal Architecture
Uncle Bob Alistair Cockburn
Concentric Layers Ports & Adapters
Dependency Rule Dependency Inversion
Focus on Use Cases Focus on Ports

Both share similar goals.


SOLID Principles

Clean Architecture relies heavily on SOLID.

  • Single Responsibility
  • Open Closed
  • Liskov Substitution
  • Interface Segregation
  • Dependency Inversion

Especially

Dependency Inversion Principle


Spring Boot Integration

flowchart TD

CLIENT[React]

CONTROLLER[REST Controller]

USECASE[Application Service]

DOMAIN[Domain Model]

POSTGRES[(PostgreSQL)]

KAFKA[(Kafka)]

REDIS[(Redis)]

CLIENT --> CONTROLLER

CONTROLLER --> USECASE

USECASE --> DOMAIN

USECASE --> POSTGRES
USECASE --> KAFKA
USECASE --> REDIS

Banking Example

Transfer Money

Controller

↓

Transfer Use Case

↓

Account Entity

↓

Repository

↓

Database

Business rules never depend on Spring.


Amazon Example

Each microservice keeps its core business logic independent of infrastructure, making it easier to evolve technologies without changing domain rules.


Netflix Example

Streaming services isolate recommendation logic from delivery infrastructure, allowing teams to change databases, messaging platforms, or deployment models independently.


Uber Example

Ride pricing, dispatch, and payment logic remain separate from REST APIs, databases, and messaging systems.


Advantages

  • High Testability
  • Framework Independence
  • Database Independence
  • UI Independence
  • Easier Maintenance
  • Better Separation of Concerns
  • Long-Term Flexibility

Challenges

  • More Classes
  • Initial Learning Curve
  • More Interfaces
  • Additional Boilerplate
  • Requires Strong Design Discipline

Monitoring

Monitor

  • API Response Time
  • Use Case Execution Time
  • Database Calls
  • Repository Performance
  • Kafka Latency
  • Redis Latency
  • Exception Rates

Tools

  • Prometheus
  • Grafana
  • Datadog
  • OpenTelemetry
  • Jaeger

Common Mistakes

❌ Putting business logic inside controllers

❌ Using JPA entities as domain entities

❌ Domain depending on Spring annotations

❌ Direct database access from controllers

❌ Large service classes ("God Services")

❌ Mixing DTOs with domain models


Best Practices

  • Keep entities as plain Java objects.
  • Place business rules in use cases, not controllers.
  • Define repository interfaces in the domain layer.
  • Keep infrastructure replaceable.
  • Use dependency injection for wiring.
  • Treat frameworks as implementation details.
  • Write unit tests for use cases without requiring Spring Boot.

Common Interview Questions

What is Clean Architecture?

Clean Architecture organizes software so that business rules remain independent of frameworks, databases, and external technologies.


What is the Dependency Rule?

Dependencies always point toward the inner layers. Inner layers never depend on outer layers.


Why are entities kept framework independent?

So business rules remain reusable, testable, and unaffected by infrastructure changes.


What belongs in the Use Case layer?

Application-specific business logic, orchestration of domain entities, and coordination of repositories.


Is Clean Architecture suitable for Microservices?

Yes. Each microservice can internally follow Clean Architecture, combining independent deployment with maintainable domain logic.


Summary

Clean Architecture helps build maintainable, testable, and technology-independent software by placing business rules at the center and treating frameworks, databases, and messaging systems as replaceable implementation details.

In this article, we covered:

  • Clean Architecture fundamentals
  • Dependency Rule
  • Four architectural layers
  • Entities
  • Use Cases
  • Interface Adapters
  • Frameworks & Drivers
  • Spring Boot implementation
  • SOLID principles
  • Comparison with Layered and Hexagonal Architecture
  • Banking, Amazon, Netflix, and Uber examples
  • Best practices

Clean Architecture is widely used in enterprise Java applications because it enables long-term maintainability, easier testing, and flexibility to evolve technologies without rewriting business logic.


Loading likes...

Comments

Share a question, correction, or practical insight about this article.

Loading approved comments...