GraphQL — a query language from Facebook that allows the client to request exactly the data needed, without the redundancy of REST.
Simple analogy: REST is like ordering from a restaurant menu (only ready-made dishes). GraphQL is like ordering from a chef: "I need 200g of rice, 100g of salmon, and sauce" — exactly what you need. In REST, getting a user and their posts might require two calls: GET /users/1 then GET /users/1/posts. In GraphQL, one query fetches everything in one round trip.
Why it matters: REST often leads to over-fetching (you get 50 fields when you need 3) or under-fetching (you need 3 API calls to render one page). GraphQL eliminates both — the client declares exactly what it needs, the server returns exactly that. This is especially impactful for mobile apps where bandwidth is expensive, and for complex UIs with nested data requirements.
Dependency:
1<dependency>2 <groupId>org.springframework.boot</groupId>3 <artifactId>spring-boot-starter-graphql</artifactId>4</dependency>
Schema (schema.graphqls):
1type User {2 id: ID!3 name: String!4 email: String!5 posts: [Post!]6}78type Post {9 id: ID!10 title: String!11 content: String!12}1314type Query {15 user(id: ID!): User16 users: [User!]17}1819type Mutation {20 createUser(name: String!, email: String!): User!21}2223subscription {24 userCreated: User!25}
Controller:
1@Controller2public class UserGraphQLController {3 @QueryMapping4 public User user(@Argument Long id) {5 return userService.findById(id);6 }78 @SchemaMapping9 public List<Post> posts(User user) {10 return postService.findByUserId(user.getId());11 }1213 @MutationMapping14 public User createUser(@Argument String name, @Argument String email) {15 return userService.create(new CreateUserRequest(name, email));16 }17}
Client (query):
1query {2 user(id: 1) {3 name4 posts {5 title6 }7 }8}
We get ONLY the name and post titles — without extra fields.
Production pitfalls:
posts resolver triggers a separate DB query. Fix with @BatchMapping to batch-load.@Cacheable.When GraphQL is better than REST: Mobile applications (bandwidth-sensitive), frontend with different data needs per view, complex relationships between entities, microservices that need to aggregate data from multiple sources (gateway pattern).