Jasmin puts an AMQP broker between you and the mobile network
Jasmin - Open source SMS gateway
At a glance
- What is it?
- Jasmin is an open source SMS gateway written in Python on Twisted, with SMPP and HTTP on both sides, RabbitMQ for store and forward, Redis for delivery receipts and billing, a console for configuration and routing rules from simple round robin to least cost. It is infrastructure you run yourself, and it comes with a real operator dependency.
- Who is it for?
- Jasmin is worth adopting if you send a meaningful volume of SMS and want to own the gateway layer, because the broker backed store and forward, the per user billing model and the routing rules are things a hosted provider will not hand you, and the console makes reconfiguring live traffic feasible. It is the wrong choice if you send a handful of messages a month, if you cannot run RabbitMQ and Redis, or if you need features the routing list does not cover.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A gateway is the thing between your application and the operator
Jasmin is described as a very complete open source SMS Gateway with many enterprise-class features, and the feature list tells you what that means in practice.
There is an SMPP client and server, and an HTTP client and server. So Jasmin can talk to a mobile operator's SMSC over SMPP, and it can accept your application's requests over HTTP, and it can also send messages out over HTTP to an operator that exposes that instead.
There is console based configuration with no service restart required, which for a live gateway is a significant operational property rather than a convenience. There is support for Unicode, UTF-8, for sending out multilingual SMS. There is support for specialized and binary SMS such as mono ringtones, WAP Push and Vcards, and for concatenated SMS strings, the long messages that are sent in parts.
The audience is a business that sends SMS at volume and wants to control the layer between its software and the operator. An app developer with a verification code form does not need a gateway, it needs an API. A company with ten thousand subscribers and a need to route by country, or by cost, or by which bind has capacity, does.
The project is maintained by Jookies LTD, and the readme credits DigitalOcean as a supporter. It also credits Dominic Amato for the port to Python 3, which is a useful signal about the project's age, and the SMPP work is credited to the smpp.pdu, smpp.twisted and python-messaging projects, so the protocol layer is built on existing work rather than written from scratch.
Why the stack is a broker, Redis and Twisted
The architecture section of the readme says Jasmin relies heavily on message queuing through message brokers using AMQP, that it is designed for performance, high traffic loads and full in-memory execution, and that the core and its external connectors for AMQP, Redis, SMPP, HTTP and Telnet are written in Python and are mainly based on Twisted, an event driven networking engine.
Those three decisions are connected. A gateway that must survive an operator connection dropping, a broker restarting and a worker being killed cannot hold the message queue in its own process, so the queue lives in RabbitMQ. The Twisted model, event driven rather than thread per connection, is what makes thousands of concurrent operator connections and HTTP requests tractable in Python. And the in-memory execution claim depends on the state that must be fast, the delivery receipts and the billing counters, living in Redis rather than on disk.
The dependency list in the project metadata shows the same shape. Twisted at 23.10 is the core. txAMQP3 is the AMQP client. txredisapi and redis are the Redis side. smpp.pdu3 and smpp.twisted3 are the SMPP protocol and transport, python-messaging provides the GSMP 3.38 support. Falcon is the REST API framework, and it is marked in the requirements file with a comment saying For REST API, while python-mimeparse and tabulate and treq are the supporting pieces. Celery is there for the background task work, prometheus-client for the metrics exporter, and cryptography and pyopenssl for the TLS the HTTP side needs.
One detail in that list is a small warning sign. The requirements file carries the comment that lockfile is abandoned, and that it should be swapped to filelock in a follow-up. A dependency marked abandoned in the project's own file is a fact a reader should carry into a risk assessment.
The routing table is where the business logic lives
Jasmin supports advanced message routing and filtering, and the README names the strategies: Simple, Roundrobin, Failover, HLR lookup and Leastcost.
Simple is one bind, always. Roundrobin spreads across the available binds. Failover sends to the next bind when one fails. HLR lookup consults a home location register to decide which route to use, which is how you route an international message to a network that actually serves that country. And Leastcost picks the bind that is cheapest for the destination.
That list is the feature that makes Jasmin more than a relay, because each of these strategies encodes a business rule about your traffic. A support platform that must prefer the cheapest route during a price change, an international service that must avoid a bind that cannot reach a country, a marketing campaign that must fail over before it loses a message, each of those is one strategy away.
The other half of the model is the user account. The readme mentions Redis being used for in-memory DLR tracking and billing, and DLR is delivery receipt, the confirmation that the operator accepted and delivered a message. Billing counters per user are what let you run Jasmin as a multi tenant gateway where each of your own customers has a balance and a rate.
So the picture is a gateway that holds accounting and routing state in memory, persists nothing about messages except through the broker, and exposes the whole thing over HTTP and SMPP. That is a coherent design for throughput, and it is also why the operational dependencies are not optional.
Configuration lives in the console, and it does not need a restart
One feature deserves its own paragraph because it changes how you run the thing. The configuration is console based, with no service restart required.
For a gateway that is carrying traffic, that is a real property. A configuration change that requires a restart means dropped connections and a deployment window, and it means the configuration becomes part of the release process rather than part of the running system. With a console, you can add a bind, change a route or adjust a user balance on a live system.
The cost is that configuration becomes runtime state, and the usual questions follow. Where does the console configuration live, is it persisted, and what happens to it when the process restarts? The readme does not answer those, and the documentation at docs.jasminsms.com is where you would look. It is a fair question to ask before you rely on the property, because a configuration that is lost on restart is a different thing from a configuration that can be changed live.
The deployment options in the readme are broad. There is a Docker image with a build workflow badge, an Ubuntu package and a Redhat package, both on packagecloud, a Kubernetes deployment section in the installation documentation, and a Procfile and app.json in the repository for a Heroku deploy template. The documentation itself is built with Sphinx from the misc directory, with the make html target, and the whole project is a Python package built with setuptools from pyproject.toml.
The compose file shows the real shape of the deployment
The docker-compose.yml in the repository is more informative than a feature list, because it names the pieces you actually have to run.
There is a Redis service on the redis:alpine image with a healthcheck that runs redis-cli ping and greps for PONG, and resource limits of 0.2 CPUs and 128 megabytes. There is a RabbitMQ service on rabbitmq:3.10-management-alpine with a healthcheck running rabbitmq-diagnostics -q ping, limited to 0.5 CPUs and 525 megabytes. And there is Jasmin itself, built from ./docker/Dockerfile.dev, with a volume mount for the jasmin directory, limited to one CPU and 256 megabytes, and with the no-new-privileges security option applied to all three services.
The published ports are three of them, 2775, 8990 and 1401, and the service waits for both Redis and RabbitMQ to report healthy before it starts, with depends_on and the service_healthy condition. The environment passes the two hostnames, REDIS_CLIENT_HOST and AMQP_BROKER_HOST.
The resource limits are the interesting part, because they tell you the intended scale. A quarter of a CPU for Redis, half a CPU for the broker and a full CPU for the gateway is a small footprint, consistent with a design that leans on the broker and the cache rather than on local computation.
There are two more compose files in the repository root, docker-compose.restapi.yml and docker-compose.grafana.yml, which indicates that the REST API and the Grafana dashboard are optional pieces you add when you want them, and the prometheus-client dependency is the other half of that observability story.
Licence, versions, and a project that has moved on
The licence question needs a sentence of care. The readme says Jasmin is released under the terms of the Apache License Version 2 and points at the LICENSE file, and the pyproject.toml declares license = Apache-2.0 with the classifier for the Apache Software License. The repository metadata for the project, however, reports the licence as a custom one that GitHub cannot classify. For a deployment that will be covered by a compliance process, the LICENSE file is the thing to read.
The version story is the other thing to note. The most recent tagged releases are 0.11.0 on 2023-11-10 and 0.10.12 on 2022-09-26, while the project metadata is at version 0.12. So the working tree is ahead of the last release tag by a version, and the pyproject declares the requirement of Python >=3.11 and <3.13, with classifiers for 3.11 and 3.12.
The repository is not archived and the last push was on 2026-04-26. That is the date to anchor on when you are planning an upgrade, rather than an assumption that the current release tag is what you would get.
The support surface is broad for a project of this age. There is a GitHub discussions link, a Google group for the SMS gateway, continuous integration on GitHub Actions, a documentation build, and a SECURITY.md file. What you do not see in the readme is a statement about which versions are still supported, so the version question is one to ask rather than one to infer.
Where Jasmin is the wrong tool
There are two clear boundaries, and one of them is the important one.
The important one is that Jasmin is a gateway, not a carrier. It terminates connections from your application and forwards them to a bind, and a bind is the operator side, an SMSC you have an agreement with. Without a bind, Jasmin has nothing to send to. The routing strategies assume multiple binds to choose between, the HLR lookup assumes you have an HLR to consult, and the least cost strategy assumes you have per bind pricing. So Jasmin is the wrong tool for anyone who wants to send SMS without a relationship with a mobile operator, and adopting it does not avoid that relationship, it puts a layer in front of it.
The second is the operational weight. Two stateful services, RabbitMQ and Redis, plus a Twisted process, plus a console whose configuration is runtime state. That is a reasonable thing to run if you send a lot of messages and you already operate infrastructure. It is a heavy thing to run if you send a few hundred a day, and at that scale a plain HTTP call to an operator's API does the same job with nothing to keep alive.
Then there is the smaller operational point. The README says the design is for full in-memory execution, and Redis holds the delivery receipt and billing state. That is excellent for throughput and it means the delivery receipt and balance information live in a cache. If Redis is the thing that loses its data, the gateway's accounting is the thing you have to reconstruct, so the durability story for the numbers you bill on is worth asking about before you put a customer's balance behind it.
A last note on what is not in the feature list: there is no mention of a delivery receipt archive, a per message audit trail, or a back office, so if you need to answer a customer question about a message sent eight months ago, that work is yours to build.
Editorial conclusion
Jasmin is worth adopting if you send a meaningful volume of SMS and want to own the gateway layer, because the broker backed store and forward, the per user billing model and the routing rules are things a hosted provider will not hand you, and the console makes reconfiguring live traffic feasible. It is the wrong choice if you send a handful of messages a month, if you cannot run RabbitMQ and Redis, or if you need features the routing list does not cover. Before you deploy it, read the installation guide at docs.jasminsms.com, confirm you have a bind with an SMPP or HTTP interface to connect to, and note that the last release tag is 0.11.0 from 2023-11-10 while the project metadata is at version 0.12, and the last push was on 2026-04-26.
Frequently asked questions
What is Jasmin and who is it for?
Jasmin is an open source SMS Gateway with enterprise-class features, including an SMPP client and server, an HTTP client and server, console based configuration with no service restart required, advanced message routing and filtering, and Unicode and concatenated SMS support. It is aimed at organisations sending SMS at volume that want to own the gateway layer.
What does Jasmin need to run?
The docker-compose.yml in the repository shows Redis on the redis:alpine image and RabbitMQ on rabbitmq:3.10-management-alpine alongside the Jasmin service, with the gateway waiting for both to be healthy. The Python dependencies include Twisted, txAMQP3, txredisapi, Celery, Falcon for the REST API and prometheus-client for metrics.
Which message routing strategies does Jasmin support?
The readme lists Simple, Roundrobin, Failover, HLR lookup and Leastcost. Each one encodes a rule about which bind a message goes to, from a single default bind through failover and home location register lookups to picking the cheapest route for the destination.
What licence is Jasmin released under?
The readme says Jasmin is released under the terms of the Apache License Version 2 and points to the LICENSE file, and the pyproject.toml declares license = Apache-2.0 with the Apache Software License classifier. The repository metadata separately reports the licence as a custom one that GitHub cannot classify, so the LICENSE file is the source to read.
What is the latest Jasmin release?
The most recent tagged releases are 0.11.0 on 2023-11-10 and 0.10.12 on 2022-09-26, while the project metadata in pyproject.toml is at version 0.12. The repository is not archived and the last push was on 2026-04-26, and it requires Python 3.11 or 3.12.
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/jookies-jasmin)Was this useful?