Skip to content

Support Keep-Alive for GraphQL Subscriptions over SSE with Spring WebFlux/WebMvc #1048

Open
@jma-9code

Description

Description:
Currently, when using GraphQL Subscriptions over Server-Sent Events (SSE) with Spring WebFlux or Spring WebMvc, there is no built-in mechanism to support keep-alive. This is a significant issue because, without a keep-alive mechanism, intermediary tools such as load balancers or proxies might close the connection due to inactivity.

For WebSocket, a keep-alive mechanism is available, which helps to maintain the connection alive over time. A similar solution is needed for SSE to ensure stable and persistent connections.

Workaround:
At present, a common workaround involves sending a dummy business object at regular intervals to keep the connection alive. Here’s an example:

@SubscriptionMapping(value = "notifications")
public Flux<UserNotification> notifications() {
    var data = getLoggedUser()
        .flatMapMany(user -> userNotifService.streamNotificationsByUser(user.getId()));
    var keepAlive = Flux.interval(java.time.Duration.ofSeconds(30))
        .map(i -> UserNotification.builder().id("-1").build());
    return Flux.merge(data, keepAlive);
}

In this example, a dummy UserNotification object with a fake ID is sent every 30 seconds to prevent the connection from being closed. While this approach works, it is far from ideal and can add unnecessary complexity and overhead to the application.

Proposed Solution:
Introduce a configuration property similar to the one used for WebSocket, such as:

spring.graphql.sse.keepalive: Duration

Instead of sending dummy business objects, this feature could automatically send an SSE event with an empty data payload and a "ping" event type at the specified interval. For example:

event: "ping"
data: \n\n

This configuration would allow developers to specify a keep-alive interval for SSE connections, ensuring that the connection remains open and active, thus preventing premature disconnection by intermediary tools. The principal implementation support this ping inside his parser => https://github.com/enisdenjo/graphql-sse/blob/master/src/parser.ts

Importance:
Supporting a keep-alive mechanism for SSE is critical for production environments where long-lived connections are necessary for real-time data streams. Without this feature, GraphQL Subscriptions over SSE are less reliable, particularly in environments where network infrastructure may close idle connections.

Thank you for considering this feature request.

Metadata

Assignees

Labels

in: webIssues related to web handlingtype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions