SAMA is a free, open source data security & privacy project written in JavaScript and released under GPL-3.0. It has 158 GitHub stars, 14 forks and 2 open issues, and was last pushed 8 days ago. On this registry it ranks #14 of 14 tracked projects in Data Security & Privacy, with 5 head-to-head comparisons available.

What is SAMA?

SAMA is a self-hostable, GPL-3.0 chat server written in JavaScript and powered by uWebSockets.js, aimed at developers and teams who want to run their own real-time messaging backend instead of adopting XMPP.

What it is

SAMA stands for Simple but Advanced Messaging Alternative. It is a chat server that lives in the Node.js ecosystem and is built on uWebSockets.js for its WebSocket transport, with MongoDB and Redis backing the stored data. The project ships as a server, not as a finished product: the same organisation publishes a frontend web client (sama-client) and a Flutter client (sama-client-flutter), so the server is intended to be paired with one of those clients or with a client built against its own API. It is licensed under GPL-3.0 and is tagged with topics such as chat-server, websocket, nodejs, xmpp and xmpp-server.

The concrete problem it addresses is the absence of a modern, widespread open messaging standard. The README states the motivation directly: the project intends to provide an alternative to the XMPP messaging protocol, which it describes as the only widely spread "standard" these days. Where XMPP carries decades of extension history and a large specification surface, SAMA replaces it with a JSON-speaking WebSocket server and a set of documented HTTP APIs covering Users, Conversations, Messages, Activities, Address Book and Push Notifications. A team that wants messaging semantics it can read end to end, rather than an XMPP stanza and extension stack, is the audience the project is written for.

Key capabilities

  • Chat server built on uWebSockets.js, exposing WebSocket endpoints for real-time message delivery.
  • Six documented API surfaces: Users API, Conversations API, Messages API, Activities API, Address Book API and Push Notifications API, with a reference at docs.samacloud.io.
  • Horizontal scaling through node clustering, with per-node liveness tracked in Redis.
  • Redis keys written as sama-node-data:{node-endpoint}, where the endpoint is a WebSocket URL such as ws://192.168.1.13:55495/, stored as an HSET with a TTL equal to the ws.cluster.nodeExpiresIn config value in seconds plus five.
  • MongoDB for persisted application data and Redis for cluster coordination.
  • Ready-made clients: sama-client for the web and sama-client-flutter for mobile.
  • Docker-based deployment path documented under the Docker server setup guide.

Who uses it and how

  • Teams that want to own their messaging backend rather than rent one, deploying the server on infrastructure they control.
  • Operators running more than one node, who rely on the Redis sama-node-data:{node-endpoint} records and the ws.cluster.nodeExpiresIn TTL to let nodes discover and expire one another.
  • Developers integrating the web client sama-client or the Flutter client sama-client-flutter against their own server instance.
  • Evaluators who want to exercise the entire stack before committing, using the public cloud deployment at app.samacloud.io.

Getting started

The README points to the Docker server setup guide at docs.samacloud.io/deployment/docker-server-setup/, which covers local development, complete deployment and end-to-end tests. A public cloud instance of the full stack is available at app.samacloud.io for evaluation before self-hosting.

How it compares

The facts name only one comparable tool, XMPP, which the project explicitly positions itself against as an alternative messaging protocol. Both are open and self-hostable, but SAMA is a single GPL-3.0 JavaScript server on uWebSockets.js with its own JSON APIs, rather than a specification implemented by many independent servers and clients. No list of paid products that SAMA replaces is provided, so no licence, cost or data-ownership comparison against commercial chat platforms can be made here.

When to use it — and when not to

A self-hoster must operate the full stack: Node.js, MongoDB, Redis and the Docker tooling the deployment guide assumes, plus the push notification path if mobile clients are in scope; no SMTP or other ancillary service is mentioned, so do not assume one. The README itself is thin, deferring explanation to Medium posts and docs.samacloud.io, and the project carries a modest 158 stars and 14 forks, so anyone needing a large third-party integration ecosystem or extensive pre-existing deployment literature should weigh that before committing. It is also GPL-3.0, which matters to teams that cannot accept copyleft terms in the products they build on top of.

project readme (upstream, from github) — read inline

SAMA - Simple but Advanced Messaging Alternative - Chat server

Powered by uWebSockets.js

Last commit GitHub issues GitHub stars GitHub license Documentation GitHub language count GitHub top language

NodeJS MongoDB Redis AWS

Screenshot 2022-12-31 at 14 15 04

Motivation

The intention of our messaging protocol and chat server, which are different from others, is to provide an alternative solution to the wide spread XMPP messaging protocol (and to be honest — the only wide spread ‘standard’ these days).

Read complete medium posts Introducing SAMA and What is SAMA about what is SAMA and what problems we are trying to solve with it:

Clients:

Development & Deployment

Local Development / Compete Deployment & E2E Tests

DEMO

The whole SAMA stack can be tested using https://app.samacloud.io public cloud.

Documentation

API reference: https://docs.samacloud.io

Also, there is a set of detailed articles for each API on Medium:

Community and Support

Join our community for support and discussions:

License

GPL-3.0

Help us!

Any thoughts, feedback is welcome! Please create a GitHub issue for any feedback you have.

Want to support us?

Buy Me A Coffee

Node Clustering

What data is stored in Redis by each node ?

sama-node-data

Record key in redis like sama-node-data:{node-endpoint} where {node-endpoint} ws url like ws://192.168.1.13:55495/, so redis record will be sama-node-data:ws://192.168.1.13:55495/. The record is HSET with ttl that equal config value ws.cluster.nodeExpiresIn in seconds + 5 seconds. The record has key/values like ip/port/host etc.

sama-node-users

Record key in redis like sama-node-users:{node-endpoint}. The record is SET that contains list user users connected to this node, user item is string like {organizationId}:{userId}:{deviceId}. Item example: 683db8ecdb9dee54f53304c0:683db9ed29aecb9feb4afb73:38400000-8cf0-11bd-b23e-10b96e40000d

sama-user-devices

Record key in redis like sama-user-devices:{organizationId}:{userId}. The record is SET that contains list user devices ids connected to all nodes. Item example: 38400000-8cf0-11bd-b23e-10b96e40000d

sama-user-data

Record key in redis like sama-user-data:{userId}:{deviceId}. The record in HSET that contains extra user session data e.g. active/inactive status

How nodes discover each other ?

Each node write record key in Redis like sama-node-data:{node-endpoint} where {node-endpoint} it is own ws url. Node create this record on start and update on sync cluster (check method syncCluster). In sync method node retrieve all records from Redis with prefix sama-node-data:, the parse record ws url part ({node-endpoint}) and try establish ws connection if it doesn't already exist.

How nodes connect to each other ?

If node-A does not have establish connection with node-B, node-A will create ws connection (check method createConnectionWithNode). When ws with node-B endpoint (node-endpoint) successfully opened - node-A send like 'ping' message with own network data (ip/port/host etc.) to node-B (check method shareCurrentNodeInfo), node-B send to node-A like 'pong' message with own network data, node-A after receiving 'pong' message - connection successfully established and handshake finished, app resolve promise and save ws connection in local object (check prop clusterNodesConnections). Node-B after send 'pong' message start connecting with node-A by same flow

What happens when connection breaks between 2 nodes ?

If connecting breaks between 2 nodes, node detect it by ws event close, and start reconnecting (check method startNodeReconnecting and promiseQueueWithJittering, prop closeNodesConnections), this method try 3 time create connection until the first successful with delay '1/4/9 seconds', flow like 1 second delay - try connect (if success return) - 4 seconds delay - try connect (if success return) - 9 seconds delay - try connect (if success return) - failed

What happens when new node added to cluster ?

2 Ways (node-A,node-B - running, node-C - new node in cluster)

  • Flow How nodes discover each other and then How nodes connect to each other. Node-C retrieve redis records (sama-node-data) created by node-A,node-B and create ws connections with each node (open ws and then connect flow with 'ping'/'pong').

  • Node-A,node-B in method syncCluster with call with interval that equal config value ws.cluster.nodeExpiresIn in ms, retrieve sama-node-data records and see new node record created by node-C and then create connection with node-C

What happens when existing node removed from cluster ?

Example with node-A and node-B

When node-B disconnect from cluster, ws connection breaks and node-A start reconnecting with node-B but it will not be success. Then on next syncCluster iteration (or next + 1 iteration) node-A can't find node-B record in sama-node-data records, but has active reconnecting state with node-B, then mean that node-B destroyed because no-one update node-B sama-node-data record ttl, then node-A cancel reconnecting and clean redis data creates by node-B (sama-node-users/sama-user-devices/sama-user-data), sama-node-data already deleted by redis ttl.

Conditions when node mark other nodes like destroyed and should clean data ?

It can be detected no syncCluster iteration

  • If have active node record sama-node-users w/o ttl, but do not have record sama-node-data - no-one update record so node is destroyed
  • If do not have node record sama-node-data but has reconnecting state
  • If have connection (check prop clusterNodesConnections) but do not have record sama-node-data (case when some how ws close was not called)
How its data is cleared from Redis ?

Check method cleanDestroyedNodeData that clea

readme truncated — read the full docs on github

Frequently asked questions

Is SAMA free to use?

SAMA is open source under the GPL-3.0 licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does SAMA do?

Secure, scalable chat server for modern applications

What is SAMA written in?

SAMA is primarily written in JavaScript. Its source is publicly available at https://github.com/sama-communications/sama-server, and it has 158 GitHub stars.