GWS WebSocket server and client for Go
simple, fast, reliable websocket server & client, supports running over tcp/kcp/unix domain socket. keywords: ws, proxy, chat, go, golang...
At a glance
- What is it?
- GWS is an Apache-2.0 licensed Go library for event-driven WebSocket servers and clients, including compressed messaging, broadcast support, file transfer, and TCP, KCP, or Unix socket transports. It fits Go developers building long-lived connection systems, but its exported error semantics and per-connection goroutines require deliberate application design.
- Who is it for?
- GWS is appropriate for Go developers who need direct control over WebSocket connections, event callbacks, compression, fan-out, and multiple transport types. It is a weaker choice for applications that expect HTTP-oriented lifecycle handling or want returned errors to describe every failure without inspecting connection state.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Where GWS fits in a Go connection stack
GWS addresses applications that maintain persistent WebSocket connections rather than isolated request and response exchanges. The README identifies API gateways, reverse proxies, chat and IM systems, online games, real-time streaming, push and subscribe services, and long-lived connection hubs as intended uses. Those workloads share a simple requirement: each peer can remain connected, send messages, receive control frames, and eventually disconnect. GWS exposes that lifecycle through an event interface and also supports client connections.
The primary language is Go, and `go.mod` declares Go 1.20. It is therefore a library embedded in a Go application, not a standalone proxy process or command-line server. Developers need to decide how HTTP upgrades, connection registration, authorization, session storage, and application shutdown are handled around the library. The repository includes focused source files such as `upgrader.go`, `client.go`, `conn.go`, `session_storage.go`, `task.go`, and `writefile.go`, which indicates that server and client concerns are separated rather than hidden in a framework abstraction.
GWS also supports TCP, KCP, and Unix domain sockets. That matters when WebSocket traffic must cross an internal network boundary or avoid the public HTTP stack. The README includes dedicated KCP and proxy examples, but its visible documentation does not explain every transport-specific deployment requirement. TCP remains the conventional path for this library's core use case, while the alternatives are relevant where the surrounding infrastructure already provides a suitable datagram or local-socket transport.
GWS connection lifecycle and event flow
GWS uses an event-driven design based on the `Event` interface. Each callback corresponds to a WebSocket lifecycle event: `OnOpen`, `OnMessage`, `OnPing`, `OnPong`, and `OnClose`. The interface separates protocol events from business code, allowing an application to handle connection registration, payload processing, heartbeat behavior, and cleanup without rewriting the frame parser.
The documented architecture assigns a goroutine to each connection to drive its event loop. Events can be processed without blocking that loop, which is important when message handling involves queues or other asynchronous work. The repository layout also exposes `task.go` and documents built-in task queues, `Writev`, and `WritevAsync`. These names point to asynchronous write paths for applications that cannot serialize all outgoing work behind one blocking call.
Protocol handling includes context takeover through `permessage-deflate`, with configurable sliding window sizes. Compression can reduce the volume of repetitive text, but it introduces explicit CPU and memory costs rather than operating as an unconditional optimization. The README's published microbenchmarks distinguish compressed and uncompressed reads and writes, showing that compression changes operation cost. Those figures belong to the repository's benchmark setup and should not be treated as a result for a different workload.
The README also states that GWS passes all Autobahn cases and complies with RFC 6455 and RFC 7692. That is a useful standards signal, although the visible documentation does not explain which feature combinations were enabled for a particular application configuration.
Installing GWS and running its published benchmark
The README gives a single installation command for adding the latest release to a Go module. Run it from the directory containing the application's `go.mod` file. The `-v` flag asks the Go command to print package information as it resolves the module.
go get -v github.com/lxzan/gws@latestAfter installation, the README provides a concrete command for exercising the repository's benchmark code. This is not an application example, but it is the first complete executable interaction documented in the visible instructions and confirms that Go can resolve and compile the package in its benchmark environment.
go test -benchmem -run=^$ -bench ^BenchmarkConn_ github.com/lxzan/gwsThe command selects benchmarks whose names begin with `BenchmarkConn_`, disables ordinary tests through `run=^$`, and requests allocation statistics with `-benchmem`. The README shows results for read and write operations with compression disabled and enabled. The repository also contains an `examples/echo` directory, which is the natural starting point for a server use case, but the visible instructions do not provide its source or an exact launch command. Following the README strictly, that example should be inspected in the repository rather than reconstructed with guessed constructor names or flags.
For a normal first integration, the sequence is therefore to add the module, inspect `examples/echo` for a basic event callback, and select `examples/chatroom` or `examples/push` when shared sessions or fan-out are part of the target design. The README does not document a rollback procedure for the module version, so an application that needs reproducible deployments should record the selected version in its own `go.mod` and `go.sum`.
Reading modes and application-level backpressure
GWS documents three ways to read data from `Conn`. `ReadLoop` is the event-driven mode and invokes the normal connection lifecycle callbacks, including `OnMessage`, `OnPing`, `OnPong`, and `OnClose`. It is described as the default fit for regular servers and clients. `ReadMessage` manually retrieves one complete message but does not produce the same `OnOpen` or `OnMessage` callbacks. `NextReader` streams message payloads and is intended to avoid retaining a complete message in memory.
That split is a real design decision, not a cosmetic API variation. An event-driven server usually needs its application callbacks to return control quickly, especially when the per-connection goroutine must continue processing protocol events. A manual reader may suit a protocol adapter or state machine where each read follows an application-defined sequence. A streaming reader is the better documented choice for large messages, although `WriteFile` is the repository's explicit mechanism for segmented writing of large files.
Backpressure still belongs partly to the application. The feature list describes built-in task queues and non-blocking writes, but it does not establish a universal policy for a slow consumer, memory limits, retry behavior, or queue saturation. Those details should be checked in the selected configuration and example before accepting unbounded client payloads or scheduling unlimited outbound work.
The README gives a direct operational warning for `net/http` upgrades: call `ReadLoop` in a separate goroutine. Otherwise, the blocking read can prevent the request context from being garbage-collected in time. This is an easy requirement to overlook because it sits outside the WebSocket callback definitions themselves.
Compression, broadcast, and large-transfer trade-offs
Compression and broadcast are separate features with different implementation costs. GWS supports context takeover with `permessage-deflate` and configurable sliding window sizes. Its `Broadcaster` reuses compressed frames for fan-out, which is particularly relevant when the same message is delivered to many subscribers. The repository names `compress.go` and `broadcast` behavior as distinct concepts, so enabling compression does not by itself guarantee that every outgoing message is broadcast efficiently.
Large transfers have another boundary. `WriteFile` segments writes to reduce peak memory, but the README explicitly warns that one connection transferring a very large file can occupy bandwidth and I/O for a long time. GWS does not claim that segmented writes solve congestion control. The application may need throttling, sharding, or another flow-control policy when connection fairness matters.
Proxy dialing is also supported through a customizable `Dialer`, with SOCKS5 and HTTP proxy use named in the README. That is useful for client-side topology, but it does not mean GWS itself is a complete reverse proxy. The `examples/proxy` directory and server upgrade code must provide the actual forwarding and policy behavior required by the application.
For chat, push, and subscribe systems, session bookkeeping is another concern outside the frame parser. The repository includes `session_storage.go`, and examples exist for chatroom, push, and pub/sub. Those examples are more relevant to an adoption decision than a generic echo benchmark because they show how connection ownership and fan-out can be composed around GWS.
GWS maintenance, licensing, and upgrade surface
The repository is not archived. Its last push was on 2026-09-11, which is recent relative to the project information available here. The recent release history includes `v1.10.2` on 2026-09-11, `v1.10.1` on 2026-07-27, and `v1.10.0` on 2026-07-10. The `v1.10.0` release note says it added the `ReadMessage` and `NextReader` APIs, so the reading-mode split is a recent API change to review when upgrading an existing integration.
The project is licensed under Apache-2.0. That identifies the published license, but it is not a substitute for checking how the license interacts with the surrounding application, dependency tree, distribution model, and any separate obligations. The repository also lists `github.com/klauspost/compress`, `github.com/stretchr/testify`, and several indirect Go dependencies in `go.mod`.
The main upgrade cost is API and behavior review rather than a separate service deployment. Go module files, dependency versions, callback code, and the selected examples should be checked together. The README does not document a compatibility matrix for each release or a formal deprecation policy. The repository's Makefile does provide concrete project commands for tests, benchmarks, coverage, and cleaning the `bin` directory, but it is aimed at repository maintenance rather than application operators.
Editorial conclusion
GWS is appropriate for Go developers who need direct control over WebSocket connections, event callbacks, compression, fan-out, and multiple transport types. It is a weaker choice for applications that expect HTTP-oriented lifecycle handling or want returned errors to describe every failure without inspecting connection state. Before adoption, verify Go version compatibility, callback behavior in the relevant example, memory requirements for the expected concurrent connection count, and whether large transfers will need throttling or sharding. For an initial integration, confirm that the selected `examples/echo`, `examples/chatroom`, or `examples/wss` program matches the deployment shape before writing production handlers.
Frequently asked questions
How do I install GWS for a Go project?
Run `go get -v github.com/lxzan/gws@latest` from the Go module that will use the library. The repository declares Go 1.20 in `go.mod`.
Which GWS API should I use for reading WebSocket messages?
Use `ReadLoop` for the normal event-driven server or client flow. Use `ReadMessage` to pull one complete message manually, or `NextReader` to stream a message payload without holding the whole message in memory.
Does GWS support WebSocket compression and large file transfer?
The README documents context takeover through `permessage-deflate` with configurable sliding window sizes. It also documents `WriteFile` for segmented large-file writes that reduce peak memory, while warning that large transfers may require application-level throttling or sharding.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/lxzan-gws)Was this useful?