Affected: Relay Proxy v6.0+ with client-side SDKs and mobile SDKs
Symptoms
When testing Relay Proxy streaming endpoints with curl or other HTTP clients, you may observe the following:
The
/eval/{envId}/{context}endpoint sends only "ping" events with no flag dataThe
/meval/{context}endpoint sends only "ping" events with no flag dataDirect LaunchDarkly endpoints (
clientstream.launchdarkly.com/meval) send "put" events with flag data directly in the stream
Example curl output showing ping events only:
class="language-auto"curl -H "Authorization: mob-..." https://your-relay-proxy.com/meval/{contextBase64}
event: ping data:Cause
The Relay Proxy uses a ping-then-poll streaming pattern that differs from LaunchDarkly's direct service endpoints. This design is intentional and optimized for the Relay Proxy's Redis-backed data store architecture.
Here's how it works:
The SDK connects to the streaming endpoint (
/evalor/meval).The Relay Proxy sends "ping" events through the stream when flag data changes.
The SDK automatically makes a separate polling request to
/sdk/evalxor/msdk/evalxafter receiving each ping.The polling endpoint returns the actual flag evaluation data.
This pattern allows the Relay Proxy to:
Maintain real-time connectivity through the persistent stream
Fetch context-specific flag data on demand
Optimize bandwidth by only sending flag data when needed
Work efficiently with Redis-backed local evaluation
Solution
For SDK usage
When using LaunchDarkly SDKs, the ping-then-poll pattern works automatically. You do not need to take any action. The SDK handles both parts:
Connecting to the stream and receiving ping events
Automatically polling for flag data after each ping
Ensure your SDK configuration includes both streamUrl and baseUrl pointing to your Relay Proxy:
class="language-auto"const client = LDClient.initialize('your-client-side-id', {
streamUrl: 'https://your-relay-proxy.com:8030',
baseUrl: 'https://your-relay-proxy.com:8030'
});In your network logs, you will see:
One persistent streaming connection to
/evalor/meval(stays open)Periodic polling requests to
/sdk/evalxor/msdk/evalx(triggered by ping events)
Both requests go through your Relay Proxy, which is the expected behavior.
For manual testing with curl
When testing manually with curl, you only see ping events because curl does not have code to react to those pings and make additional requests. To verify the full flow, make two separate requests:
For mobile endpoints:
# Connect to stream (shows ping events)
curl -H "Authorization: mob-..." \ https://your-relay-proxy.com/meval/{contextBase64}
# Poll for flag data in a separate request
curl -H "Authorization: mob-..." \ https://your-relay-proxy.com/msdk/evalx/contexts/{contextBase64}For client-side JavaScript endpoints:
# Connect to stream (shows ping events)
curl https://your-relay-proxy.com/eval/{envId}/{contextBase64}
# Poll for flag data in a separate request
curl https://your-relay-proxy.com/sdk/evalx/{envId}/contexts/{contextBase64}To verify your Relay Proxy is working correctly:
Check the
/statusendpoint returns healthy.Verify the streaming endpoint sends ping events.
Confirm the polling endpoint returns flag data.
If all three pass, your Relay Proxy is functioning as designed.
Troubleshooting SDK connections
If your SDKs are not receiving flag updates, verify the following:
Your SDK configuration includes both
streamUrlandbaseUrlpointing to your Relay Proxy.Your Relay Proxy
/statusendpoint returns healthy.The polling endpoints
/sdk/evalxor/msdk/evalxare accessible.Network logs show both streaming and polling requests going to your Relay Proxy.