Why OpenFeign’s First Call Is Slow and How to Fix It

The article analyzes why the first OpenFeign call in micro‑service systems incurs seconds of latency, breaks down five root causes such as lazy client initialization, dynamic proxy creation, load‑balancer cold start, network handshake, and hidden dependencies, and provides concrete verification steps and four practical optimizations to move the cost to application start‑up.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Why OpenFeign’s First Call Is Slow and How to Fix It

Problem Overview

In high‑concurrency micro‑service scenarios (e.g., flash‑sale), the first call from a service using OpenFeign can take several seconds, while subsequent calls are fast. The delay is caused by the lazy initialization of the Feign client and related components, which adds ~2.3 s of processing plus the TCP/TLS handshake.

Typical Scenarios Affected by First‑Call Latency

Flash‑sale: the first inventory‑deduction request stalls, causing stock to be deducted but the order to time out.

Admin backend: the first export of a report blocks for ~5 s, leading to repeated retries.

Service health‑check after startup: a delayed probe can trigger false‑positive alarms.

Root Causes – Burst of Initialization Cost

The first‑call latency originates from five groups of operations that are performed lazily on the first Feign invocation.

1. Lazy‑load of Feign client bean

Spring creates the Feign client only when it is first used. Initialization includes loading configuration, creating a dynamic proxy, binding a load‑balancer, and building the HTTP client.

public class FeignClientFactoryBean implements FactoryBean<Object> {
    @Override
    public Object getObject() {
        // 1. Load Feign context
        FeignContext context = applicationContext.getBean(FeignContext.class);
        // 2. Build Feign builder
        Feign.Builder builder = feign(context);
        // 3. Create dynamic proxy (executed only on first call)
        return targeter.target(this, builder, context, new HardCodedTarget<>(…));
    }
}

2. Dynamic proxy generation

JDK dynamic proxy creation is 3‑5× slower than a normal object. Enabling CGLIB ( proxy-target-class=true) adds byte‑code generation overhead.

3. Load‑balancer cold start

Spring Cloud LoadBalancer loads the service list and performs health checks on first use; with many instances this can add hundreds of milliseconds.

4. First network handshake

TCP three‑way handshake (~1 ms) and optional TLS handshake (50‑200 ms) are incurred on the first remote call. The default URLConnection client creates a new connection each time, increasing cost.

5. Implicit dependencies

Feign’s Encoder, Decoder, Logger, etc., are also lazily loaded. For example, Jackson’s ObjectMapper may take 100‑300 ms to load modules for complex DTOs.

Verification Methods

Enable Feign FULL logging to see timing of each phase.

Set a breakpoint in FeignClientFactoryBean.getObject() and inspect the call stack.

Key breakpoint locations:

FeignClientFactoryBean.getObject()
Feign.Builder.target()
LoadBalancedRetryFactory.createRetryer()

Practical Optimizations – Move Initialization to Application Startup

1. Disable lazy loading (eager load) for Feign clients

Globally disable lazy initialization (use with caution) or eagerly initialize only Feign beans.

spring:
  main:
    lazy-initialization: false   # globally disable lazy init

@Configuration
public class FeignEagerLoadConfig {
    @Autowired(required = false)
    private List<FeignClientSpecification> feignClientSpecifications;

    @PostConstruct
    public void initFeignClients() {
        FeignClientFactoryBean factory = new FeignClientFactoryBean();
        for (FeignClientSpecification spec : feignClientSpecifications) {
            factory.setBeanFactory(applicationContext);
            factory.setSpecification(spec);
            factory.getObject(); // trigger init
        }
    }
}

Result: first‑call latency drops from ~3 s to ~150 ms (network only).

2. Warm‑up core Feign clients after start‑up

@Service
public class FeignWarmUpService {
    @Autowired private PayFeignClient payFeignClient;
    @Autowired private InventoryFeignClient inventoryFeignClient;

    @PostConstruct
    public void warmUp() {
        new Thread(() -> {
            try {
                Thread.sleep(3000); // wait for registry, DB, etc.
                payFeignClient.healthCheck();
                inventoryFeignClient.healthCheck();
                log.info("Feign client warm‑up completed");
            } catch (Exception e) {
                log.warn("Feign warm‑up failed", e);
            }
        }).start();
    }
}

3. Replace URLConnection with HttpClient or OkHttp and enable connection pooling

<!-- Maven dependency (escaped) -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

feign:
  httpclient:
    enabled: true
    max-connections: 200
    max-connections-per-route: 50
    connection-timeout: 2000

Result: network latency reduced from ~150 ms to ~20 ms thanks to connection reuse.

4. Pre‑load LoadBalancer service list

@Configuration
public class LoadBalancerConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> reactorLoadBalancer(
            Environment env, LoadBalancerClientFactory factory) {
        String name = env.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RoundRobinLoadBalancer(
                factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}

Best‑Practice Summary (8‑Year Experience)

Core services (order, payment, etc.) should use eager loading + warm‑up; the extra start‑up time is worthwhile for fast first requests.

Non‑core services can use lightweight @PostConstruct warm‑up to balance start‑up cost.

Initialize implicit dependencies (e.g., Jackson ObjectMapper) early to avoid hidden latency.

By moving all heavy initialization from the first request to application startup, the unpredictable “first‑call” penalty becomes a controllable part of the system’s start‑up phase.

JavaPerformance optimizationMicroservicesSpring CloudOpenFeignFeign Client
Java Architect Handbook
Written by

Java Architect Handbook

Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.

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.