Why build another job runner?
Most Ruby job libraries lean on Redis or Postgres — tools that were never designed to be message brokers. We wanted an engine built for messaging first.
- Redis: KV first
- NATS: messaging first
Ruby gem · jobs + streams · NATS
Background jobs and real-time event streaming for Ruby — one gem, backed by NATS.
No Redis. No DB polling.
No message silently dropped.
Transmissions · blog
Redis is a brilliant key-value store that learned to queue. NATS is a messaging system that learned to store. That difference is the whole reason Cosmonats exists.
Read transmission →Mission log
Most Ruby job libraries lean on Redis or Postgres — tools that were never designed to be message brokers. We wanted an engine built for messaging first.
One NATS server replaces your message broker, job queue and KV store — with far less to operate.
A first-class Job and a first-class Stream, sharing one server, one config, one CLI and one monitoring endpoint.
Messages persist to disk. Rewind a consumer to the beginning of time, a timestamp, or only new messages.
Clusters and leaf nodes are built into NATS. Spanning regions is a config block, not another product. Lose a node, lose nothing.
Same-ID messages inside the window are dropped before they reach a worker. A built-in KV store handles locks and rate limits.
Mount Cosmo::Web for a live dashboard of jobs, streams, crons and batches — retry, pause and run from one place.
Tens of millions of jobs processed and counting. Horizontally scalable, and no message is ever silently dropped.
Touchdown · taste it
class SendEmailJob
include Cosmo::Job
options stream: :default, retry: 3, dead: true
def perform(user_id, template)
EmailService.send(user_id, template)
end
end
SendEmailJob.perform_async(123, "welcome")
SendEmailJob.perform_in(1.day, 123, "followup")
class ClicksProcessor
include Cosmo::Stream
options stream: :clickstream, batch_size: 100,
consumer: { subjects: ["events.clicks.>"] }
def process_one
Analytics.track(message.data)
message.ack
end
end
gem "cosmonats"
docker run -p 4222:4222 -p 8222:8222 nats:alpine -js
bundle exec cosmo -C config/cosmo.yml -c 20