DEV Community

DevCorner2
DevCorner2

Posted on

πŸ“¦ Industry-Wide Folder & Packaging Structures in Spring Boot

Spring Boot is one of the most popular Java frameworks for building scalable web applications. But writing good code isn't enoughβ€”structuring your project properly is equally crucial. The right folder/package structure:

  • Enhances code readability and maintainability
  • Helps teams scale and collaborate
  • Aligns with domain modeling and microservices architecture

In this blog, we’ll explore the most commonly adopted folder structures across the industry, with examples, pros & cons, and when to use what.


🧱 1. Standard Layered Architecture

πŸ‘€ Best For: Monoliths, small-to-mid web apps

This is the most traditional structure used by most teams starting with Spring Boot.

com.example.myapp
β”œβ”€β”€ controller         // REST Controllers
β”œβ”€β”€ service            // Business logic
β”œβ”€β”€ repository         // Spring Data Repositories
β”œβ”€β”€ model              // JPA Entities or POJOs
β”œβ”€β”€ dto                // Request/Response DTOs
β”œβ”€β”€ config             // Spring Boot Configs
β”œβ”€β”€ exception          // Custom exceptions, handlers
β”œβ”€β”€ mapper             // MapStruct or manual mappers
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Easy to learn and organize
  • Aligned with typical 3-tier architecture

❌ Cons

  • Can get bloated in large projects
  • Tightly couples layers

🧠 Example

@RestController
@RequestMapping("/users")
public class UserController {
    private final UserService userService;
    @GetMapping("/{id}")
    public UserDto getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

🧩 2. Feature-Based Modular Structure (Vertical Slice)

πŸš€ Best For: Medium to large modular apps

Organized by feature instead of layers. Ideal when teams work on distinct modules.

com.example.myapp
β”œβ”€β”€ features
β”‚   β”œβ”€β”€ user
β”‚   β”‚   β”œβ”€β”€ controller
β”‚   β”‚   β”œβ”€β”€ service
β”‚   β”‚   β”œβ”€β”€ repository
β”‚   β”‚   β”œβ”€β”€ dto
β”‚   β”‚   β”œβ”€β”€ model
β”‚   β”‚   └── mapper
β”‚   └── product
β”‚       β”œβ”€β”€ controller
β”‚       β”œβ”€β”€ service
β”‚       β”œβ”€β”€ repository
β”‚       └── dto
β”œβ”€β”€ config
β”œβ”€β”€ exception
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Scales well with multiple teams
  • Each feature is self-contained

❌ Cons

  • Slight learning curve
  • Shared logic must be carefully managed

🧱 3. Hexagonal Architecture (Ports & Adapters / Clean Architecture)

πŸ›οΈ Best For: Domain-Driven, long-lived enterprise systems

Separates domain, application logic, and infrastructure clearly.

com.example.myapp
β”œβ”€β”€ domain
β”‚   β”œβ”€β”€ model
β”‚   └── service
β”œβ”€β”€ application
β”‚   └── usecases
β”œβ”€β”€ infrastructure
β”‚   β”œβ”€β”€ persistence
β”‚   └── rest
β”œβ”€β”€ web
β”‚   └── controller
β”œβ”€β”€ config
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Testable and decoupled
  • Clean separation of concerns

❌ Cons

  • More boilerplate and upfront design
  • Not suited for trivial apps

πŸ”Œ Example:

public interface UserRepository {
    Optional<User> findById(Long id);
}
Enter fullscreen mode Exit fullscreen mode

Implemented by an adapter in infrastructure.persistence.


🧳 4. Multi-Module Maven Structure

🧬 Best For: Microservices, shared modules

Each feature is an independent module, often maintained in different repos.

project-root/
β”œβ”€β”€ common/                   // Shared DTOs, utils
β”‚   └── src/main/java/...
β”œβ”€β”€ user-service/
β”‚   └── src/main/java/com/example/user
β”œβ”€β”€ product-service/
β”‚   └── src/main/java/com/example/product
└── pom.xml                   // Parent POM
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Clear modular boundaries
  • Reusable components

❌ Cons

  • Maven complexity
  • Shared versioning can be tricky

🌊 5. Reactive Structure (WebFlux / Handler-Based)

βš›οΈ Best For: Reactive, async applications

Uses functional routing over MVC annotations.

com.example.myapp
β”œβ”€β”€ handler             // Functional endpoint handlers
β”œβ”€β”€ router              // RouterFunction configs
β”œβ”€β”€ service
β”œβ”€β”€ repository
β”œβ”€β”€ model
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

Example Router

@Bean
public RouterFunction<ServerResponse> route(UserHandler handler) {
    return RouterFunctions
           .route(GET("/users/{id}"), handler::getUser);
}
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Non-blocking, high throughput
  • Lightweight functional style

❌ Cons

  • Functional style is less familiar
  • Debugging stack traces is harder

βš”οΈ 6. CQRS-Oriented Structure

🧠 Best For: High-scale systems, Event Sourcing

Separates read and write logic.

com.example.myapp
β”œβ”€β”€ command
β”‚   β”œβ”€β”€ handler
β”‚   β”œβ”€β”€ service
β”‚   β”œβ”€β”€ controller
β”œβ”€β”€ query
β”‚   β”œβ”€β”€ service
β”‚   β”œβ”€β”€ controller
β”œβ”€β”€ events
β”‚   └── listeners
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Optimized for scale
  • Clear boundaries

❌ Cons

  • Higher complexity
  • Eventual consistency challenges

πŸ•ΈοΈ 7. GraphQL-Driven Structure

πŸ” Best For: GraphQL-first APIs

com.example.myapp
β”œβ”€β”€ graphql
β”‚   β”œβ”€β”€ resolver
β”‚   β”œβ”€β”€ schema
β”‚   β”œβ”€β”€ dto
β”‚   └── service
β”œβ”€β”€ repository
└── MyAppApplication.java
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

  • Logical schema-based grouping
  • Supports GraphQL-first development

❌ Cons

  • Requires GraphQL learning
  • Less RESTful structure

πŸ“Š Comparison Table

Structure Type Use Case Pros Cons
Layered Monoliths Easy, traditional Bloated in large apps
Feature-Based Modular, team-split projects Scalable, modular Shared code management
Hexagonal Clean DDD applications Decoupled, testable Design-heavy
Multi-Module Microservices, shared libs Isolated, reusable Maven/Gradle complexity
Reactive WebFlux-based async apps Lightweight, fast Less IDE-friendly
CQRS Event-based systems High throughput Complex to maintain
GraphQL GraphQL-first BFF or APIs Schema-aligned Requires schema tooling

πŸ› οΈ Which Structure Should You Use?

Your Need Recommended Structure
Building a quick CRUD API Layered
Multi-team, large-scale product Feature-based
Long-term investment, strong domain logic Hexagonal / Clean
Need shared libraries or services Multi-module
Reactive WebSockets / streaming Reactive
Split reads and writes cleanly CQRS
GraphQL-first application GraphQL-based

πŸ“ Final Thoughts

There’s no one-size-fits-all. The right structure depends on your:

  • Team size
  • Codebase complexity
  • Domain modeling
  • Delivery expectations

Start simple, and evolve your structure as the system grows.


🧰 Bonus: Generate Feature Skeleton with Spring Boot CLI

spring init --dependencies=web,data-jpa --build=maven --package-name=com.example.user user-service
Enter fullscreen mode Exit fullscreen mode

Want a GitHub Starter Template?

πŸ‘‰ Drop a comment or message, and I’ll share a starter repo matching your preferred structureβ€”layered, modular, reactive, or clean architecture.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.