Weaviate Streaming API Incomplete Results Under High Traffic
Problem – Symptoms and Impact
During peak load the /v1/objects/{className}/{id}/stream endpoint returns truncated JSON payloads or the client receives a connection reset by peer error. Typical observations include:
- Logs in Weaviate:
2024-05-12T14:23:07Z WARN streaming response incomplete: expected 12456 bytes, got 8421 - API gateway (Kong) reports:
504 Gateway Timeout – upstream timed out after 30s - NGINX error log:
2024/05/12 14:23:08 [error] 112#112: *3456 upstream sent unexpected EOF while reading response header from upstream, client: 10.0.0.12, server: weaviate.example.com, request: "GET /v1/objects/Article/123/stream HTTP/2.0" - Client SDKs raise
ReadTimeoutError: streaming response timed out.
The effect is partial search results, broken client UI components, and increased retry traffic, amplifying the load problem.
Root Cause Analysis
The streaming endpoint uses HTTP/2 server push with a long-lived response body. Under high concurrency the following chain of events can cause premature termination:
- API gateway timeout – Kong’s default
proxy_read_timeoutis 30 seconds (see GitHub issue #1589). When a vector search takes longer, Kong closes the upstream connection, emitting a GOAWAY frame. Weaviate logs “HTTP/2 GOAWAY received”. - Proxy buffer limits – NGINX with default
proxy_buffer_size 4kcannot hold the streaming payload during spikes (see Company Y incident). The buffer overflows, causing NGINX to truncate the response and log “upstream sent unexpected EOF”. - Keep‑alive and idle timeout mismatches – Envoy’s
idle_timeout 15s(Open‑source project Z) forces a GOAWAY after 15 seconds of inactivity, cutting off streams that are still emitting vectors. - Weaviate connection limits – The default
max_open_connections(see Weaviate Scalability guide) is 100. When 500+ concurrent streams are opened, excess connections are rejected, leading to “connection reset by peer”.
All these factors converge on the same symptom: the upstream proxy or Weaviate itself terminates the HTTP/2 stream before the full payload is delivered.
Investigation and Debugging Steps
Follow this checklist to isolate the component responsible:
- Collect end‑to‑end logs
# Weaviate logs (JSON format) journalctl -u weaviate -f | grep streaming # Example excerpt {"ts":"2024-05-12T14:23:07Z","lvl":"WARN","msg":"streaming response incomplete: expected 12456 bytes, got 8421","class":"Article","id":"123"} - Inspect API gateway metrics
# Kong admin API curl -s http://localhost:8001/services/weaviate/metrics | grep proxy_read_timeout # NGINX status curl -s http://localhost/nginx_status - Capture HTTP/2 frames (requires
tcpdumpandnghttp2tools)tcpdump -i eth0 -w weaviate.pcap port 443 nghttp -v -d weaviate.pcapLook for
GOAWAYframes with error codeNO_ERRORorENHANCE_YOUR_CALM. - Check proxy buffer statistics
# NGINX cat /var/log/nginx/error.log | grep "proxy_buffer" # Expected line when overflow occurs 2024/05/12 14:23:08 [error] 112#112: *3456 upstream sent unexpected EOF while reading response header from upstream - Validate Weaviate connection limits
# Weaviate config dump curl -s http://localhost:8080/v1/.well-known/openid-configuration | jq .max_open_connections # Default is 100
Resolution – Configuration and Deployment Changes
Apply the following adjustments. Each block shows the configuration before and after the change.
1. Increase API gateway timeouts
Kong
# Before (default)
proxy_read_timeout = 30s
# After
proxy_read_timeout = 120s
proxy_send_timeout = 120s
Reason: Allows long‑running vector searches to finish without the gateway closing the upstream connection.
2. Raise NGINX proxy buffer sizes
# Before (default)
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# After
proxy_buffer_size 64k;
proxy_buffers 16 64k;
proxy_busy_buffers_size 128k;
Reason: Prevents buffer overflow that truncates streaming payloads (see Company Y incident).
3. Align Envoy keep‑alive settings with Weaviate
# Before
idle_timeout: 15s
# After
idle_timeout: 300s
max_connection_duration: 0s # disable forced termination
Reason: Avoids premature GOAWAY frames that cut off active streams.
4. Increase Weaviate max open connections
# weaviate.conf (YAML)
# Before
max_open_connections: 100
# After
max_open_connections: 1000
Reason: Accommodates the 500+ concurrent streams observed during load tests (FinTech startup incident).
5. Enable HTTP/2 flow control tuning (optional)
# weaviate.conf
http2:
initial_window_size: 65535 # default 64KB
max_frame_size: 16384 # increase if large vectors are streamed
Reason: Reduces the chance of flow‑control stalls under heavy load.
Verification – How to Confirm the Fix
- Run a load test with
heyork6targeting the streaming endpoint, e.g.:hey -c 500 -n 5000 "https://weaviate.example.com/v1/objects/Article/123/stream"Observe zero “connection reset by peer” or “streaming response incomplete” messages in Weaviate logs.
- Check gateway metrics for timeout counters; they should remain at zero during the test.
- Validate full payload size:
curl -s https://weaviate.example.com/v1/objects/Article/123/stream | wc -c # Should match the expected byte count reported by Weaviate metadata endpoint - Confirm no GOAWAY frames in a fresh packet capture:
nghttp -v -d weaviate.pcap | grep GOAWAY # No output indicates streams remain open until completion
Prevention – Operational Best Practices
- Monitor gateway timeout metrics (Kong
proxy_read_timeout_total, NGINXproxy_timeout) and set alerts for spikes. - Track Weaviate connection usage via
/metricsendpoint (weaviate_http_connections_open). - Configure health checks that verify a complete streaming response (e.g., a synthetic request that expects a known byte count).
- Capacity plan for peak concurrency by running load tests that exceed expected traffic by 20‑30 % and adjusting
max_open_connectionsaccordingly. - Align keep‑alive and idle timeout values across all proxies (Kong, NGINX, Envoy) and Weaviate to avoid mismatched closures.
FAQ – Related Questions
- Why does the streaming API work in dev but fail in production?
Production uses an API gateway (Kong/NGINX) with default timeout and buffer settings that are too low for long‑running vector searches, whereas the dev environment hits Weaviate directly. - Can I disable HTTP/2 and fall back to HTTP/1.1 to avoid GOAWAY?
Disabling HTTP/2 removes flow‑control benefits and may increase latency. The recommended approach is to tune timeouts and keep‑alive rather than disabling HTTP/2. - What metric should I watch to detect upcoming streaming truncation?
Watchweaviate_http_stream_errors_totaland the gateway’sproxy_read_timeout_total. A rising trend indicates impending truncation. - Is increasing
max_open_connectionsenough for all workloads?
Only if the underlying OS limits (ulimitnofile) are also raised. Verify withulimit -nand adjust the systemd service file accordingly. - Do client SDKs need any changes after fixing the gateway?
No. The SDKs already handle HTTP/2 streams correctly; they only need the server side to keep the connection alive for the full duration of the response.
Related Topic Hub: Vector Databases Troubleshooting Hub