Spring Boot
REST API
Java
ResponseEntity
POJO

Return ResponseEntity vs returning POJO

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In a Spring MVC or Spring Boot controller, returning a plain object and returning ResponseEntity both produce HTTP responses, but they communicate different levels of intent. A plain object is ideal when the default HTTP behavior is correct, while ResponseEntity is the tool to reach for when status codes, headers, or conditional response logic are part of the contract.

Returning a POJO

If a controller method returns a regular Java object and the method is in a @RestController, Spring serializes that object through an HttpMessageConverter, usually as JSON.

java
1import org.springframework.web.bind.annotation.GetMapping;
2import org.springframework.web.bind.annotation.RestController;
3
4@RestController
5public class UserController {
6
7    @GetMapping("/users/me")
8    public UserDto currentUser() {
9        return new UserDto(1L, "[email protected]");
10    }
11
12    public record UserDto(Long id, String email) {}
13}

This is the cleanest style when the response is simply "return this representation with a normal success status." It keeps controller code short and lets Spring use the default 200 OK behavior.

That simplicity is a real advantage in CRUD endpoints where there is no need to alter headers or branch on multiple HTTP outcomes. The controller reads like business code instead of transport plumbing.

Returning ResponseEntity

ResponseEntity wraps the body together with HTTP metadata. Use it when the endpoint needs explicit control over status codes, response headers, or whether a body is present at all.

java
1import java.net.URI;
2import org.springframework.http.ResponseEntity;
3import org.springframework.web.bind.annotation.PostMapping;
4import org.springframework.web.bind.annotation.RequestBody;
5import org.springframework.web.bind.annotation.RestController;
6
7@RestController
8public class UserController {
9
10    @PostMapping("/users")
11    public ResponseEntity<UserDto> create(@RequestBody CreateUserRequest request) {
12        UserDto created = new UserDto(42L, request.email());
13        URI location = URI.create("/users/" + created.id());
14        return ResponseEntity.created(location).body(created);
15    }
16
17    public record CreateUserRequest(String email) {}
18    public record UserDto(Long id, String email) {}
19}

Here ResponseEntity expresses two important HTTP details: the response is 201 Created, and the Location header points to the new resource. Returning only a POJO would lose that semantic information unless another mechanism added it.

How to Decide Between Them

A useful rule is:

  • return a POJO when the default status and headers are correct
  • return ResponseEntity when the HTTP envelope matters

Examples where ResponseEntity is usually the better fit include:

  • '201 Created after resource creation'
  • '204 No Content for delete operations'
  • '404 Not Found from controller logic'
  • custom headers such as pagination or caching metadata
  • conditional responses based on validation or authorization state

If every controller method returns ResponseEntity by habit, the code can become noisy. If no method ever returns it, developers start hiding transport decisions in exceptions or filters that may be harder to reason about.

Error Handling and Consistency

One subtle point is that controller design and global exception handling should work together. Many teams return plain objects for successful responses and let @ControllerAdvice handle error responses centrally. That often produces the cleanest architecture.

ResponseEntity is still valuable in that setup when the success path itself needs explicit HTTP control. The question is not which approach is universally better. The question is where the response metadata belongs for a given endpoint.

Common Pitfalls

  • Returning ResponseEntity everywhere even when a plain object would be clearer.
  • Returning only POJOs from endpoints that need custom status codes or headers.
  • Mixing ad hoc ResponseEntity handling with inconsistent exception handling.
  • Using controller return types to hide domain problems that should be modeled explicitly.
  • Forgetting that transport concerns are part of the public API contract.

Summary

  • Returning a POJO is best when default Spring response behavior is correct.
  • 'ResponseEntity is best when status codes, headers, or empty bodies matter.'
  • Use ResponseEntity deliberately, not as boilerplate.
  • Keep success-path design aligned with your exception-handling strategy.
  • Choose the return style that makes the HTTP contract obvious to readers and clients.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.