The web is increasingly realtime. Whether it’s chat, sports score updates, or collaborative workspaces, moving data with minimal latency is now a core functionality for many web and mobile apps, as well as less visible infrastructure such as fleets of IoT devices.
In recent years, the WebSocket standard has replaced older HTTP-based workarounds as the default way to enable two-way realtime communication on the web. However, during the early days of WebSocket, projects such as SockJS aimed to bridge the gap between the two approaches by switching automatically to whichever technique was available from one client to the next.
What is WebSocket?
WebSocket is an industry-standard protocol and API for transferring data in realtime between clients and servers. Unlike earlier workarounds, such as HTTP long polling, WebSocket is designed from the ground up for realtime communication. It achieves that by establishing a persistent, bidirectional connection between the client and server and exchanging data as and when required.
That persistent connection is key to delivering a realtime experience. HTTP-based methods rely on a response-request pattern, meaning that each transfer of data also comes with the overhead of setting up the connection and acknowledging the data transfer. The WebSocket specification also reduces the overhead required to maintain the connection, bringing latency to a minimum.
Key features of WebSocket
Full duplex: Communication over WebSocket is bidirectional, with data going in either direction simultaneously.
Persistent connections: WebSocket connections stay open for as long as they’re needed. That both reduces latency introduced by protocol overhead and, following the initial setup, ensures that the connection is available instantly when needed.
Official standard: As a common standard, maintained by the working group responsible for the future of HTML, WebSocket is as close as we have to an official realtime communication protocol.
Highly efficient: Older techniques for ongoing communication between client and server tend to rely on HTTP, which is both stateless and designed for short-lived connections. That means they rely on opening fresh connections for each data transfer, adding significant overhead, especially for smaller messages. By providing a truly persistent connection, WebSocket removes the overhead of repeatedly setting up and closing new connections. WebSocket also uses very small frame headers, up to a maximum size of 14 bytes. HTTP ’s headers, on the other hand, are an order of magnitude larger at 800 bytes. Then we have to consider cookies used for authentication and other supplemental data, which can get to kilobytes in size. Across hundreds or thousands of connections, the latency difference between HTTP-based techniques and WebSocket is substantial.
Widely available: WebSocket enjoys almost universal support, with all current versions of major supported offering WebSocket.
Message format flexibility: WebSocket specifies how to set up and maintain an ongoing connection between a client and server. But the application-level protocol you choose and the trade-offs you want to make are up to you. For example, in an online game, you might choose a custom binary format that prioritizes small message sizes for faster delivery, but at the expense of needing to create and maintain your own encoding/decoding functionality. Where raw speed is less of a concern, choosing a format with extensive tooling, such as JSON, could reduce your reliance on custom code with no noticeable impact on your application experience.
Not suited to audio or video data: WebSocket is designed for sending discrete messages, rather than continuous streams of data. That means there’s no mechanism to alter bitrate according to network conditions, for example. And, although WebSocket is generally very efficient, by relying on TCP for transport it does have more overhead related to quality control than UDP-based protocols.
Lacks automatic connection recovery: For pure WebSocket, you’ll need to implement additional logic in your own code to detect and manage disconnections.
Harder to scale horizontally: HTTP is stateless, meaning that each request can complete successfully without knowing the state of any other HTTP request. That makes it easy to put multiple HTTP servers behind a load balancer, because it doesn’t matter which one serves a request. As an ongoing point to point connection, WebSocket can’t be stateless, which makes it harder to scale out a WebSocket application to multiple servers.
Still unavailable in some places: Although modern web browsers and devices support WebSocket, some corporate firewalls still block it.
What is SockJS?
SockJS is an open-source realtime messaging library, with both frontend and backend components, that sets out to emulate the WebSocket API. Created at a time before WebSocket was widely supported in web browsers, SockJS automatically falls back to older HTTP-based techniques, such as HTTP long polling, in situations where WebSocket is unavailable.
The commitment to implement the WebSocket API does limit SockJS, somewhat. For example, it is harder for SockJS to offer features that don’t appear in WebSocket, such as data broadcast or multiplexing, but that are available in competing solutions.
Key features of SockJS
Automatic fallback: SockJS lets you target use cases where WebSocket support is unpredictable, such as where users might be behind a strict corporate firewall, by automatically switching to HTTP long polling if necessary.
WebSocket API compatibility: SockJS emulates the WebSocket API on both the client and the server.
Open source: If you are prepared to take on the maintenance burden, you can amend SockJS to your own needs and create versions that support languages and frameworks other than those already available.
Works even where WebSocket is unavailable: In those rare cases where a corporate firewall blocks WebSocket connections, or the client is ancient enough to lack support for WebSocket, SockJS will fall back to older mechanisms, such as HTTP long polling.
Some basic support for horizontal scaling: SockJS doesn’t manage horizontal scaling by itself. Instead, it provides some conveniences that enable you to use a load balancer, such HAProxy, to distribute requests across multiple SockJS instances. For example, SockJS can prefix each request with a server ID number that the load balancer can use to ensure requests from a particular client always hit the same server (i.e. sticky sessions).
The alternatives have left SockJS behind: SockJS solves a problem that is close to irrelevant now that WebSocket is universally available and corporate firewalls tend not to block the protocol. Realtime platforms such as Ably and libraries such as Socket.IO offer more functionality and a better developer experience.
Development has stalled: Recent SockJS releases have focused on solving security issues rather than adding new features and, since 2015, development has been sporadic. With no new features, the relevance of SockJS is waning and that could lead to a lack of maintenance.
Risk of increased latency: Although SockJS gives you the same development experience, regardless of which underlying communication technique it uses, the end-user experience will vary. For example, if SockJS falls back to HTTP long polling then latency will leap. That means that you’ll still need to design your software for circumstances where latency is higher than you’d expect from WebSocket.
No automatic reconnections: Although the SockJS client triggers an event when a connection drops, you’ll need to write your own code to repair the connection manually.
What is the difference between WebSocket and SockJS?
The principle difference between WebSocket and SockJS is that WebSocket is a universal standard and SockJS is just one of several ways to build WebSocket into your app. For example, if you’re developing your backend using NodeJS then the ws library offers a lightweight and fast WebSocket implementation. For .NET developers, WebSocket is natively implemented in the framework.
Should I use WebSocket or SockJS?
Perhaps the questions we should ask are:
Does SockJS still solve meaningful problems today?
Are there better ways to implement WebSocket in my app?
The answer to the first question is “no”. SockJS offers nothing other than automatic fallback to older techniques where WebSocket is unavailable. So, choosing SockJS means trading all the modern realtime functionality on offer from realtime PaaS providers or other open-source libraries, in exchange for a solution to an already solved problem.
And we’ve just answered the second question. Yes, there are better ways to add WebSocket to your app, including:
Integrating an open-source library such as Socket.IO, which relies on WebSocket but adds higher-level functionality including automatic reconnections and multiplexing.
Working with a realtime PaaS, like Ably.
Let’s look at that third option in some more detail.
Use Ably to build scalable WebSocket applications with automatic fallback
Whichever protocol best serves your end users, building, scaling, and maintaining realtime infrastructure is a specialized task. According to research for our State of Serverless WebSocket Infrastructure report, 65% of engineering leaders who built a DIY realtime solution experienced at least one significant outage in the preceding 18 months.
Ably’s global edge network allows you to focus on serving your end users while we take care of delivering your data. Here are just some of the reasons to choose Ably for your realtime WebSocket infrastructure:
Global network reach: Scale globally thanks to a worldwide network of edge locations.
The right protocol: Ably selects the right protocol, whether that’s WebSocket, Server Sent Events, MQTT, or something else. That broadens the reach of your application but offers greater sophistication than the simple fallback offered by SockJS.
<65 ms latency: Create seamless experiences with quick response times.
Resilient delivery: Ably guarantees that messages arrive in order and on time.
99.999% uptime: Ably’s dedicated team works 24/7, so you can have peace of mind even during high-demand periods.
Elastic scaling: From thousands to billions of messages, Ably meets your application’s demands seamlessly.
A great developer experience: with SDKs targeting more than 25 languages and frameworks, integrations with common tooling, and industry-leading documentation, Ably’s developer experience gives you the tools to become productive quickly.
Discover how Ably empowers you to integrate global, scalable, and efficient realtime experiences in your apps, with a developer experience built by developers just like you.
Socket.IO vs SockJS
Compare realtime libraries Socket.IO and SockJS on performance, scalability, developer experience, and features.
Socket.IO vs. WebSocket: Key differences and which to use
We compare Socket.IO with WebSocket. Discover how they are different, their pros & cons, and their use cases.
Discover the five best alternatives to the WebSocket protocol for building realtime apps such as live chat, multiplayer collaboration, and data broadcast applications.