# How CasaOS Manages WebSocket Connections for Real-Time Updates

> Discover how CasaOS manages WebSocket connections for real-time updates. Learn about HTTP upgrades, connection storage, and efficient notification broadcasting.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: internals
- Published: 2026-06-27

---

**CasaOS uses the `gorilla/websocket` library to upgrade HTTP requests at `GET /notify/ws`, stores active connections in a global slice named `WebSocketConns`, and broadcasts JSON notifications via a background goroutine that polls the notification store every two seconds.**

CasaOS is an open-source Home Cloud system that delivers real-time UI updates through a lightweight WebSocket layer. According to the IceWhaleTech/CasaOS source code, the implementation relies on a combination of connection pooling and lazy-initialized background broadcasting to push notifications to connected clients without blocking the main application thread.

## WebSocket Upgrade and Connection Pooling

### The HTTP Endpoint Handler

In [`route/v1/notify_old.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v1/notify_old.go), the application exposes a WebSocket endpoint at `GET /notify/ws`. The handler uses a permissive `Upgrader` to convert the HTTP connection into a WebSocket connection.

```go
// route/v1/notify_old.go (lines 28-30)
ws, err := upGrader.Upgrade(ctx.Response().Writer, ctx.Request(), nil)
if err != nil {
    return err
}

```

### Global Connection Registry

Each new `*websocket.Conn` is appended to the global slice `WebSocketConns` declared in [`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go) (lines 29-30). This slice acts as a connection pool for the broadcaster to iterate over.

```go
// service/service.go
var WebSocketConns []*websocket.Conn

```

In [`notify_old.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/notify_old.go) (line 34), the handler registers the new connection:

```go
service.WebSocketConns = append(service.WebSocketConns, ws)

```

## Background Broadcasting Architecture

### Lazy-Initialized Broadcaster

To conserve resources, CasaOS starts the broadcast goroutine only when the first client connects. The boolean flag `service.SocketRun` (declared in [`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go)) ensures that only one instance of `SendMeg()` runs at a time.

In [`route/v1/notify_old.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v1/notify_old.go) (lines 36-38):

```go
if !service.SocketRun {
    service.SocketRun = true
    service.SendMeg()
}

```

### The Notification Polling Loop

The `SendMeg()` function in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) implements a polling-based broadcaster. It repeatedly queries the `Notify` service for unread application notifications (lines 298-299):

```go
list := MyService.Notify().GetList(types.NOTIFY_APP)

```

The function marshals the notification list to JSON and broadcasts it to every connection in `WebSocketConns`. Closed connections are filtered out during the broadcast loop (lines 303-311):

```go
var temp []*websocket.Conn
for _, v := range WebSocketConns {
    err := v.WriteMessage(1, json)
    if err == nil {
        temp = append(temp, v)
    }
}
WebSocketConns = temp

```

### Graceful Shutdown

When the connection pool becomes empty, the broadcaster terminates itself by setting `SocketRun = false` (lines 316-318):

```go
if len(WebSocketConns) == 0 {
    SocketRun = false
    return
}

```

The next client connection will trigger a new broadcaster instance.

## Optional Socket.io Integration

While the core implementation uses raw WebSockets, the codebase includes a `go-socket.io` server stub in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) (lines 39-41) for future event-driven extensions. The primary notification path, however, relies on the goroutine-based broadcast mechanism described above.

## Summary

- **Connection Upgrading**: CasaOS upgrades HTTP requests to WebSockets at [`route/v1/notify_old.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v1/notify_old.go) using the `gorilla/websocket` library.
- **Global Pool**: Active connections are stored in the `WebSocketConns` slice defined in [`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go).
- **Lazy Broadcasting**: The `SendMeg()` function in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) starts only when the first client connects and runs as a background goroutine.
- **Dead Connection Cleanup**: The broadcaster filters out failed connections during each broadcast cycle, preventing memory leaks.
- **Resource Efficiency**: The broadcaster automatically stops when no clients are connected, restarting only on the next connection.

## Frequently Asked Questions

### What WebSocket library does CasaOS use?

CasaOS uses the `gorilla/websocket` library for the core implementation. The upgrader is configured in [`route/v1/notify_old.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v1/notify_old.go) to handle the HTTP-to-WebSocket protocol upgrade, while the connection management relies on standard `*websocket.Conn` types from this library.

### How does CasaOS handle disconnected WebSocket clients?

During each broadcast cycle in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go), the `SendMeg()` function attempts to write messages to all connections in `WebSocketConns`. Connections that return an error on `WriteMessage` are excluded from the temporary slice, effectively removing dead connections from the global pool without explicit close handlers.

### What triggers real-time updates in CasaOS?

Real-time updates are triggered by a polling loop inside `SendMeg()` that queries `MyService.Notify().GetList(types.NOTIFY_APP)` every two seconds. When unread notifications exist, the function marshals them to JSON and broadcasts the payload to all active WebSocket connections before marking them as read.

### Does CasaOS use Socket.io for notifications?

While the codebase includes a `go-socket.io` server stub in [`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go) for future extensibility, the primary notification system uses raw WebSockets via the `gorilla/websocket` library. The Socket.io integration is not currently active in the core notification path.