Hi,
I’m running a Spring Boot reactive application using Couchbase client-core v3.8.1 and java-client v3.7.9, and I’m observing unexpectedly high latencies at the SDK layer — typically >250ms per request, even though:
Couchbase server is healthy (low CPU, fast response times)
SDK logs show OverThresholdRequestRecordedEvent warnings
Workload is light: only 100 RPS, each request performs 25 lightweight lookupIn() sub-document operations
I’m currently testing with a single pod (4 vCPU), and expected latencies would be under 100ms, but that’s not happening.
I’ve tuned eventLoopGroup, kvConnection, and thread pools as per documentation and Couchbase best practices (detailed below in configuration), but still see high latencies from the SDK.
My Pod and couchbase server are in the same region and size of returned lookup document is <1KB.
Can anyone point out what I might be missing or suggest advanced tuning tips for reactive SDK use with high-QPS KV subdoc workloads?
Thanks in advance!
Workload Overview
Environment: Java 17, Spring Boot, Linux (Epoll available)
Couchbase SDK version: 3.7.9
Pod spec: 4 vCPU, 4Gi memory
RPS: ~100 req/sec
Each request processes 25 products.
For each Product, a lookupIn() call is made → ~2,500 KV lookups/sec per pod
Using Reactive APIs with collection.lookupIn() (non-blocking)
@PostConstruct
public void initialize() {
scheduler = Schedulers.fromExecutor(Executors.newWorkStealingPool(8));
if (Epoll.isAvailable()) {
eventLoopGroup = new EpollEventLoopGroup(8);
} else {
eventLoopGroup = new NioEventLoopGroup(8);
}
}
@Override
protected void configureEnvironment(final ClusterEnvironment.Builder builder) {
builder
.jsonSerializer(JacksonJsonSerializer.create(objectMapper))
.meter(MicrometerMeter.wrap(meterRegistry))
.timeoutConfig((config) ->
config.connectTimeout(Duration.ofMillis(1000))
.kvTimeout(Duration.ofMillis(1000))
)
.ioConfig(
(config) ->
config.tcpKeepAliveTime(Duration.ofMillis(60000))
.numKvConnections(8)
.enableDnsSrv(false)
)
.publishOnScheduler(() -> scheduler)
.ioEnvironmentConfig().kvEventLoopGroup(eventLoopGroup)
.build();
}
public Mono<ProductResult> fetchPriceCompetitiveness(final String product, final List<String> locations) {
List<LookupInSpec> specs = buildLookupSpecs(locations);
return collection.lookupIn(product, specs)
.onErrorResume(DocumentNotFoundException.class, e -> Mono.empty());
}