Skip to main content

Configuring server timeouts

There are several ways to override the default timeouts at server-side.

Using ServerBuilder

import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;

import java.time.Duration;

ServerBuilder sb = Server.builder();
Server server = sb.http(port)
.annotatedService(new HelloService())
.requestTimeout(Duration.ofSeconds(5))
.build();

Using VirtualHostBuilder

You can set the timeouts for each virtual host.

import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;

import java.time.Duration;

import static com.linecorp.armeria.common.HttpStatus.OK;

ServerBuilder sb = Server.builder();
Server server = sb.http(port)
.defaultVirtualHost()
.service("/hello1", (ctx, req) -> HttpResponse.of(OK))
.requestTimeout(Duration.ofSeconds(5))
.and()
.virtualHost("*.foo.com")
.service("/hello2", (ctx, req) -> HttpResponse.of(OK))
.requestTimeout(Duration.ofSeconds(10))
.and()
.withVirtualHost(builder -> {
builder.hostnamePattern("*.bar.com")
.service("/hello3", (ctx, req) -> HttpResponse.of(OK))
.requestTimeout(Duration.ofSeconds(15));
})
.build();

Using ServiceBindingBuilder

You can set the timeouts for each route.

import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;

import java.time.Duration;

import static com.linecorp.armeria.common.HttpStatus.OK;

ServerBuilder sb = Server.builder();
Server server = sb.http(port)
.route()
.get("/hello1")
.requestTimeout(Duration.ofSeconds(5))
.build((ctx, req) -> HttpResponse.of(OK))
.withRoute(builder -> {
builder.get("/hello2")
.requestTimeout(Duration.ofSeconds(10))
.build((ctx, req) -> HttpResponse.of(OK));
})
.build();

Using ServiceRequestContext

You can use the context to set the timeouts for a request.

import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;

import java.time.Duration;

import static com.linecorp.armeria.common.HttpStatus.OK;

ServerBuilder sb = Server.builder();
Server server = sb.http(port)
.service("/hello", (ctx, req) -> {
ctx.setRequestTimeout(Duration.ofSeconds(5));
return HttpResponse.of(OK);
})
.build();

Using @RequestTimeout Annotation

You can use the @RequestTimeout annotation for annotated services and gRPC services.

HelloService.java
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.annotation.Get;
import com.linecorp.armeria.server.annotation.decorator.RequestTimeout;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

import static com.linecorp.armeria.common.HttpStatus.OK;

@RequestTimeout(value = 10, unit = TimeUnit.SECONDS)
public class HelloService {

@Get("/hello")
@RequestTimeout(5000)
public HttpResponse getHello() {
return HttpResponse.of(OK);
}

}

Handling timeouts for streaming requests

For long-running streaming requests (e.g., gRPC server streaming, bidirectional streaming, or GraphQL subscriptions), the default request timeout applies to the entire duration of the stream—from receiving the first message until responseObserver.onCompleted() is called. This means that if your stream is expected to last longer than the configured request timeout, you must manually extend the timeout as messages are sent.

You can extend the timeout dynamically using ServiceRequestContext with EXTEND:

import com.linecorp.armeria.common.util.TimeoutMode;
import com.linecorp.armeria.server.ServiceRequestContext;

import java.time.Duration;

import io.grpc.stub.StreamObserver;

public class MyStreamingService extends MyServiceGrpc.MyServiceImplBase {

@Override
public void streamingOutputCall(Request request,
StreamObserver<Response> responseObserver) {
ServiceRequestContext ctx = ServiceRequestContext.current();

for (int i = 0; i < 100; i++) {
// Simulate processing time
Thread.sleep(500);

// Send a response
responseObserver.onNext(Response.newBuilder().build());

// Extend the timeout with each message sent
ctx.setRequestTimeout(TimeoutMode.EXTEND, Duration.ofSeconds(5));
}

responseObserver.onCompleted();
}
}

You can also extend the timeout reactively when streaming with reactive publishers:

import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.util.TimeoutMode;
import com.linecorp.armeria.server.ServiceRequestContext;

import java.time.Duration;

import reactor.core.publisher.Flux;

// Extend timeout with each emitted item
ServerBuilder sb = Server.builder();
sb.service("/streaming", (ctx, req) -> {
Flux<String> publisher =
Flux.interval(Duration.ofMillis(200))
.doOnNext(i -> ctx.setRequestTimeout(TimeoutMode.EXTEND, Duration.ofMillis(500)));
return HttpResponse.of(publisher.take(100).map(i -> "data: " + i + "\n"));
});

Alternatively, for streams with unpredictable duration (e.g., infinite streams or proxy services), you can disable the timeout entirely:

// Disable request timeout for infinite streaming
ServerBuilder sb = Server.builder();
sb.requestTimeoutMillis(0)
.service("/infinite-stream", myStreamingService);
tip

See Timeout control for more details on using TimeoutMode to dynamically adjust timeouts.

Understanding timeout and cancellation origins

Timeouts and cancellations can originate from either the client or server side, and understanding this is crucial for debugging issues. For detailed information about how timeouts and cancellations propagate between clients and servers, see Understanding timeout and cancellation origins.

Global Configuration

You may globally configure the default timeout with system properties or a custom FlagsProvider.

Using FlagsProvider

You can override the request timeout specified by JVM system properties by implementing your own FlagsProvider and loading it via Java SPI.

package com.example.providers;

// Add the following text file to your classpath or JAR file:
//
// $ cat META-INF/services/com.linecorp.armeria.common.FlagsProvider
// com.example.providers.MyFlagsProvider
//
public class MyFlagsProvider implements FlagsProvider {
@Override
public int priority() {
// The provider with higher value will be evaluated first.
return 100;
}

@Override
public Long defaultRequestTimeoutMillis() {
return 1000L;
}
}

Using JVM system properties

You can override the default server timeouts by specifying the following JVM system properties if you do not prefer setting it programmatically.

-Dcom.linecorp.armeria.defaultRequestTimeoutMillis=<long>

Represents the amount of time from receiving a request to sending the corresponding response completely. Default: 10000.

warning

The JVM system properties have effect only when you did not specify them programmatically. See Flags for the complete list of JVM system properties in Armeria.

Like Armeria?
Star us ⭐️

×