Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions quickwit/quickwit-config/src/node_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub struct RestConfig {
pub struct GrpcConfig {
#[serde(default = "GrpcConfig::default_max_message_size")]
pub max_message_size: ByteSize,
/// Search server responses can be larger when returning many hits.
#[serde(default = "GrpcConfig::default_max_search_message_size")]
pub max_search_message_size: ByteSize,
#[serde(default)]
pub tls: Option<TlsConfig>,
// If set, keeps idle connection alive by periodically perform a
Expand Down Expand Up @@ -104,6 +107,10 @@ impl GrpcConfig {
ByteSize::mib(20)
}

fn default_max_search_message_size() -> ByteSize {
ByteSize::mib(60)
}

pub fn validate(&self) -> anyhow::Result<()> {
ensure!(
self.max_message_size >= ByteSize::mb(1),
Expand All @@ -118,6 +125,7 @@ impl Default for GrpcConfig {
fn default() -> Self {
Self {
max_message_size: Self::default_max_message_size(),
max_search_message_size: Self::default_max_search_message_size(),
tls: None,
keep_alive: None,
}
Expand Down Expand Up @@ -846,13 +854,15 @@ mod tests {
fn test_grpc_config_validate() {
let grpc_config = GrpcConfig {
max_message_size: ByteSize::mb(1),
max_search_message_size: ByteSize::mb(1),
tls: None,
keep_alive: None,
};
assert!(grpc_config.validate().is_ok());

let grpc_config = GrpcConfig {
max_message_size: ByteSize::kb(1),
max_search_message_size: ByteSize::kb(1),
tls: None,
keep_alive: None,
};
Expand Down
5 changes: 3 additions & 2 deletions quickwit/quickwit-serve/src/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,11 @@ pub(crate) async fn start_grpc_server(

let search_service = services.search_service.clone();
let grpc_search_service = GrpcSearchAdapter::from(search_service);
let max_message_size_bytes = grpc_config.max_search_message_size.0 as usize;
Some(
SearchServiceServer::new(grpc_search_service)
.max_decoding_message_size(grpc_config.max_message_size.0 as usize)
.max_encoding_message_size(grpc_config.max_message_size.0 as usize),
.max_decoding_message_size(max_message_size_bytes)
.max_encoding_message_size(max_message_size_bytes),
)
Comment on lines +191 to 196
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The search service is configured with the same max_search_message_size for both decoding and encoding. If the intent is only to allow larger responses, this also increases the maximum accepted request size for the search endpoint, which can have DoS/memory implications. Consider keeping max_decoding_message_size at grpc.max_message_size and only increasing max_encoding_message_size for search responses (and ensure the client-side limits mirror this).

Copilot uses AI. Check for mistakes.
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion quickwit/quickwit-serve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ async fn setup_searcher(
)
.await?;
let search_service_clone = search_service.clone();
let max_message_size = node_config.grpc_config.max_message_size;
let max_message_size = node_config.grpc_config.max_search_message_size;
let searcher_change_stream = cluster_change_stream.filter_map(move |cluster_change| {
let search_service_clone = search_service_clone.clone();
Box::pin(async move {
Expand Down
Loading