Tinode chat: GPL 3.0 server, Apache 2.0 clients, and no XMPP compatibility
Instant messaging platform. Backend in Go. Clients: Swift iOS, Java Android, JS webapp, scriptable command line; chatbots
At a glance
- What is it?
- Tinode is a self hosted instant messaging stack in pure Go, with Java, Swift, React and Python clients and a gRPC surface for everything else. Its most consequential details are the ones it refuses: it does not speak XMPP, it is not a Slack replacement, and it calls itself beta quality software.
- Who is it for?
- Tinode earns its place when you want a self hosted messenger with four first party clients, a gRPC surface for your own services, and a choice of Postgres, MySQL, MongoDB or RethinkDB behind one server, and its declared non goals are honest ones: it will not talk to XMPP and it is not building a Slack clone. Skip it if federation with an existing XMPP estate matters, if a Flutter client is non negotiable, or if a Google group is not an acceptable support channel.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 1 day 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 November 13, 2026, and from our analysis. They are not legal advice.
Star history
- tinode/chat13,571 ★ · +57
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| tinode/chat | 13.5k | 13.6k |
57 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
JSON over websocket, with long polling and protobuf as the other two doors
Tinode's wire protocol is JSON carried over a websocket, and long polling is available for clients that cannot hold a socket open. The same server also speaks protobuf over gRPC, and the repository ships gRPC client support for C++, C#, Go, Java, Node, PHP, Python, Ruby and Objective-C. That second transport is the one that matters for anything server side. A bot or an internal service that speaks gRPC never parses JSON, never writes a reconnect loop, and never has to hold a long lived websocket in the middle of its request path. The cost is that protobuf leaves the reference clients behind: the official apps are Java, Swift and React, so a gRPC consumer is working from docs/API.md rather than copying an app.
The backend is GPL 3.0 while every client is Apache 2.0
The license split is deliberate, and it is the first thing to check before you plan an architecture around this project. The backend is pure Go under GPL 3.0. The clients, Android in Java, iOS in Swift, the React.js web app and the scriptable Python command line client, are all Apache 2.0, as are the gRPC bindings. The practical effect is asymmetric. A company can build a proprietary application on the protocol and on the client libraries without inheriting copyleft, while anyone who modifies and hosts the server itself is bound by GPL 3.0. What the split does not give you is a permissively licensed core to embed in a closed product, because there is no second copy of the server in the tree. If your deployment model involves shipping the server inside someone else's appliance, that is the constraint to price in, and the gRPC surface is the part of the design to plan around, since it is the sanctioned way to talk to the server without linking the Go code at all.
Not XMPP, not compatible with XMPP, and meant to replace it
The project is blunt about its central exclusion. Tinode states that it is not XMPP or Jabber, is not compatible with XMPP, and is meant as a replacement for XMPP rather than another participant in that network. The reasoning given is that XMPP never delivered on federated messaging and that instant messengers remain a set of incompatible walled gardens, much as AOL was to the open internet in the late 1990s. The second declared non goal is equally precise: this is not another Slack replacement. Those two sentences decide who should keep reading. A team that needs its new server to interop with the XMPP deployment it already has has no path here, because there is no bridge layer to configure and no compatibility mode to enable, so migration is a cutover between two client bases at the same time. A team that wanted channel style team chat on an open source stack is also looking at the wrong project.
The sandbox resets at 3:15am Pacific and reports it as User not found or offline
The sandbox at sandbox.tinode.co wipes all data every night at 3:15am Pacific, and the way it tells you is a single error string: User not found or offline. That message means the server was reset while you were connected, and the recovery differs by client. On the web app you reload and log in again, on Android you log out and log back in, and if the database itself changed you delete the app and reinstall it. The demo logins are alice, bob, carol, dave and frank, each with the password formed as the login name plus 123, and other accounts can be discovered by prefixing an address with email: or tel:, with demo addresses at the example.com domain and phone numbers running from +17025550001 through +17025550009. One sandbox user, Tino, is a basic chatbot that answers any message with a random quote. For a reader the consequence is direct: the sandbox is a demo and a compatibility target, and an overnight integration test pointed at it will fail in a way that reads like a client bug.
The 123456 verification shortcut is one line inside tinode.conf
On the sandbox, every account you register will accept 123456 as a verification code, and the real code emailed to you works as well. The mechanism is not a build flag and not an environment variable. It is the line "debug_response": "123456" in tinode.conf, and removing that line disables the shortcut. This is the tidiest thing in the whole configuration story, and it is also the one that can hurt you, because server/tinode.conf is the same file that carries the ordinary configuration and is meant to be read and edited while you set the server up. Carry a sandbox flavoured config into a real deployment and any address on the instance can be registered without proving control of it, and the symptom would not be an error at all: the account would simply exist, and the first sign of trouble would be someone else using it. The public service at web.tinode.co does not have this shortcut and requires an account registered with a valid email address, and demo accounts that exist in the sandbox are deliberately not present there.
Four database drivers and a Go 1.26.0 floor in the same go.mod
The module declaration asks for Go 1.26.0, which is the hard floor for building the server, and the dependency list is long and pinned to exact versions. Four database backends sit side by side: pgx v5.10.0 for Postgres, go-sql-driver/mysql v1.10.0, mongo-driver v1.17.9 for MongoDB, and rethinkdb-go.v6 v6.2.2. Alongside them are firebase.google.com/go v3.13.0, the AWS SDK v2 with an S3 transfer manager, google.golang.org/grpc v1.83.2, oauth2, x/crypto, and Prometheus client_golang v1.23.2 for metrics, which pairs with the monitoring directory in the tree. For a reader this is both a strength and a decision. You can keep whichever database your operations team already runs, but you inherit its sharp edges, and the repository keeps a tinode-db/ directory next to the server that you will be reading either way. It also means an air gapped build needs vendored modules, because the exact versions above have to be present rather than merely compatible.
Four first party clients, a debug APK, and no Flutter package anywhere
Supported platforms are named concretely: Android in Java, iOS in Swift, the web app in React.js, and a scriptable command line client written in Python. Tindroid, the Android app, is described as stable and functional, ships under the package id co.tinode.tindroidx, and a debug APK is published on the releases page for convenience. Tinodios, the iOS app, gets the same description. TinodeWeb is a single page app whose default build loads one minified javascript bundle and minified CSS, with the unminified version at index-dev.html on the sandbox, which is the page to point a console at when you are debugging a client. The gap is everything else. No Flutter client appears anywhere in the repository, and the only non graphical surface is the Python command line client, so a Flutter team is writing its own client against gRPC instead of installing one. Video and voice calls are listed among the supported features.
Beta quality by declaration, with paid support sold as a separate product
The project labels itself beta quality software and then defines the term: feature complete and stable, but probably with a few bugs or missing features. That sentence sets expectations rather than promising polish, and it is the one to quote when a stakeholder asks what you are signing up for. Support runs through a Google group for general questions and discussion, GitHub issues for bugs and feature requests, and two commercial routes, a contact page for inquiries and a separate paid support page. Self service answers live in INSTALL.md, the Docker instructions under docker/, docs/API.md, docs/faq.md, and the configuration notes inside server/tinode.conf. On cadence, the last push to master is dated 2026-10-25, which is later than the newest tag, v0.25.3 on 2026-07-04, while v0.25.2 shipped on 2026-03-03, so the branch moves steadily and the tags land on a slower cadence than the commits.
Editorial conclusion
Tinode earns its place when you want a self hosted messenger with four first party clients, a gRPC surface for your own services, and a choice of Postgres, MySQL, MongoDB or RethinkDB behind one server, and its declared non goals are honest ones: it will not talk to XMPP and it is not building a Slack clone. Skip it if federation with an existing XMPP estate matters, if a Flutter client is non negotiable, or if a Google group is not an acceptable support channel. Before deploying, confirm your toolchain meets the Go 1.26.0 floor, strip the "debug_response": "123456" line out of server/tinode.conf, and treat the sandbox as disposable because it resets nightly.
Frequently asked questions
Are there any instant messengers left?
Yes, and Tinode is one of them: a self hosted instant messaging platform with a pure Go backend under GPL 3.0, first party clients for Android, iOS, the web and a scriptable command line, and a hosted public service at web.tinode.co you can use like any other messenger after registering with a valid email.
What are the three types of chat?
Tinode does not define a three way taxonomy of chat. What it supports is one-on-one and group messaging plus video and voice calls, carried as JSON over websocket, over long polling, or as protobuf with gRPC.
What is the best private chat website?
The project's own web client is TinodeWeb, a single page app served at web.tinode.co, with a disposable sandbox at sandbox.tinode.co for testing. The project makes no best claim, and it describes itself as beta quality software with a few bugs or missing features.
What is the most used messaging app in the world?
The repository publishes no user counts, install figures or market share, so it does not answer that question. What it does state is that a public service runs at web.tinode.co, a nightly reset sandbox runs at sandbox.tinode.co, and Docker images of that demo are published under the tinode user on Docker Hub.
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/tinode-chat)Star history chart for your README
[](https://hysenlabs.com/projects/tinode-chat)Was this useful?