Why Is the First Feign Call So Slow? Understanding Ribbon’s Lazy Loading and Eager‑Load Fix

The article explains that the initial Feign request is slow because Ribbon lazily creates its client and fetches the service list at first use, and shows how enabling Ribbon’s eager‑load mode pre‑warms the client to eliminate the delay.

Java Companion
Java Companion
Java Companion
Why Is the First Feign Call So Slow? Understanding Ribbon’s Lazy Loading and Eager‑Load Fix

Introduction

Feign relies on Ribbon for client‑side load balancing. When a microservice registers with Eureka or Nacos, Ribbon obtains the service list, caches it locally, and the Feign client uses this cache for remote calls.

How Ribbon Performs Load Balancing

Ribbon’s RibbonClientConfiguration injects a LoadBalancer implementation. The core interface is ILoadBalancer, which provides methods to add services, choose a server, mark a server down, and retrieve server lists (all, alive, or total).

ZoneAwareLoadBalancer Details

The default load balancer is ZoneAwareLoadBalancer, which extends DynamicServerListLoadBalancer. Its restOfInit method initializes two important functions: enableAndInitLearnNewServersFeature and updateListOfServers. The former starts a ServerListUpdater thread that continuously fetches the latest service list.

LOGGER.info("Using serverListUpdater {}", serverListUpdater.getClass().getSimpleName());
serverListUpdater.start(updateAction);

Ribbon Load‑Balancing Strategies

RoundRobinRule – cycles through servers sequentially.

WeightedResponseTimeRule – prefers servers with shorter response times.

RandomRule – selects a server at random.

BestAvailableRule – chooses the server with the fewest active connections.

RetryRule – retries failed servers within a timeout.

AvailabilityFilteringRule – filters out unhealthy instances.

ZoneAvoidanceRule – applies zone‑aware filtering.

Eager‑Load Mode ("Hungry Loading")

Ribbon creates its client only when the first HTTP request occurs. This first call includes both the network latency and the time to instantiate the client and load the server list, making it noticeably slower.

@GetMapping("/requestSystem2Api")
public String requestSystem2Api(){
    long startTime = System.currentTimeMillis();
    R<String> stringR = iTestServiceClient.testRequestMethod();
    if(stringR != null){
        log.info("Response: " + stringR.getMsg());
    }
    long needTime = System.currentTimeMillis() - startTime;
    log.info("Call duration: " + needTime);
    return "";
}

Log output shows the first invocation takes longer because DynamicServerListLoadBalancer loads the Feign client and performs the server‑list update. Subsequent calls are fast.

Enabling Ribbon Eager‑Load

ribbon:
  nacos:
    enabled: true   # enable Nacos discovery
  eager-load:
    enabled: true   # turn on eager‑load to avoid first‑call timeout
    clients: Lxlxxx-system2   # specify services to pre‑load
  ReadTimeout: 10000
  ConnectTimeout: 10000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 1
  OkToRetryOnAllOperations: false

When the application starts, logs confirm that the specified service ( Lxlxxx-system2) is loaded, preventing the initial timeout.

Conclusion

Enabling Ribbon’s eager‑load mode acts like a client‑side warm‑up, loading service metadata at startup. This is useful when inter‑service calls involve heavy business logic or large data, helping to avoid first‑request latency.

MicroservicesLoad BalancingfeignSpring CloudRibbonEager Load
Java Companion
Written by

Java Companion

A highly professional Java public account

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.