LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2220 min read

Spring Cloud Gateway & Feign Dependencies

Learn how to route microservice traffic through a single API gateway and call services declaratively using Spring Cloud Gateway and OpenFeign.

Introduction

Two problems come up constantly once you have more than one microservice: how do external clients reach the right service without knowing your internal topology, and how do your services call each other without writing repetitive RestTemplate boilerplate? Spring Cloud Gateway and OpenFeign solve these two problems respectively.

What You Will Learn
  • What an API gateway does and why microservices systems need one.
  • How to configure routes with spring-cloud-starter-gateway.
  • How to write a declarative REST client with spring-cloud-starter-openfeign.
  • How gateway and Feign fit into the rest of your Spring Cloud stack.

Why a Gateway and a Declarative Client?

Use case: external clients (browsers, mobile apps) should not need to know that "orders" live on one service and "payments" on another — a gateway presents one unified entry point and routes internally. Meanwhile, service-to-service calls (order-service calling payment-service) are far cleaner as a typed interface than as manual HTTP client code.

API Gateway: spring-cloud-starter-gateway

spring-cloud-starter-gateway builds a reactive API gateway that sits in front of your microservices, routing incoming requests to the correct backend based on path, host, or other predicates. It can also apply cross-cutting concerns like rate limiting, authentication, and request/response rewriting.

pom.xml (gateway module)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

Routes can be defined in application.yml. This example routes any request under /orders/** to order-service, and any request under /payments/** to payment-service — both resolved dynamically through Eureka using the lb:// (load-balanced) scheme.

application.yml
spring:
cloud:
gateway:
routes:
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/orders/**
- id: payment-service-route
uri: lb://payment-service
predicates:
- Path=/payments/**
Result

Click Run to see what this code prints.

Gateway Requires Eureka (or Similar) for lb://

The lb:// scheme depends on a discovery client (such as spring-cloud-starter-netflix-eureka-client) being on the classpath so the gateway can resolve service names to live instances. Without discovery, you can still route to a fixed URI directly.

Declarative Clients: spring-cloud-starter-openfeign

spring-cloud-starter-openfeign lets you define an HTTP client as a plain Java interface annotated with @FeignClient. Spring generates the implementation at runtime, so calling another service looks like calling a local method.

pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Enable Feign clients on your main application class, then declare the interface.

OrderServiceApplication.java
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
PaymentClient.java
@FeignClient(name = "payment-service")
public interface PaymentClient {
@PostMapping("/payments")
PaymentResponse createPayment(@RequestBody PaymentRequest request);
}
OrderService.java
@Service
public class OrderService {
private final PaymentClient paymentClient;
public OrderService(PaymentClient paymentClient) {
this.paymentClient = paymentClient;
}
public void checkout(String orderId, double amount) {
PaymentResponse response = paymentClient.createPayment(
new PaymentRequest(orderId, amount));
System.out.println("Payment status: " + response.status());
}
}
Result

Click Run to see what this code prints.

Common Mistakes

Avoid These Mistakes
  • Forgetting @EnableFeignClients on the main application class, which silently skips Feign interface scanning.
  • Using lb:// gateway routes without a discovery client on the classpath.
  • Not handling FeignException in calling code, letting a downstream service failure bubble up unhandled.
  • Putting business logic inside the gateway itself — a gateway should route and apply cross-cutting concerns, not contain domain logic.

Best Practices

  • Keep gateway routes declarative and simple — push authentication/authorization logic into filters, not custom controllers.
  • Group Feign client interfaces in a shared module if multiple services need to call the same downstream service.
  • Combine Feign with a circuit breaker (e.g. Resilience4j) so one slow downstream service does not cascade failures.
  • Version your internal APIs so gateway routes and Feign clients do not break silently on breaking changes.

Frequently Asked Questions

No. Zuul was Spring Cloud's older, servlet-based gateway. Spring Cloud Gateway is its reactive, Project Reactor-based successor and is now the recommended choice for new projects.

Yes. You can set a fixed url attribute on @FeignClient to call a specific host directly, bypassing service discovery entirely.

No, CORS still needs to be configured, typically at the gateway level so you only configure it once instead of on every downstream service.

Summary

spring-cloud-starter-gateway gives your system one routed entry point, and spring-cloud-starter-openfeign turns service-to-service HTTP calls into simple, typed interface methods.

Lesson 22 Completed
  • You understand what an API gateway does in a microservices system.
  • You configured routes with spring-cloud-starter-gateway.
  • You built a declarative REST client with @FeignClient.
Next Lesson →

API Documentation Dependencies (OpenAPI/Swagger)