惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks

Railway Blog

Where Railway is, and where it's going (Summer 2026) PaaS vs IaaS vs SaaS: What Each Means and Who Should Pick What in 2026 The Best Continuous Deployment Tools in 2026 The Best PaaS for Multi-Region Deployments in 2026 The Best Platforms for Monorepo Deployments in 2026 Compliance Isn't a Feature, It's a Posture What is BYOC (Bring Your Own Cloud)? A Developer's Guide for 2026 The Best Managed Kubernetes Hosting in 2026 The Best Container Registries in 2026 The Vanilla Cloud Tax: What Rolling Your Own on AWS Actually Costs What is a PaaS? A Developer's Guide for 2026 The Best Cloud Observability and Logging Tools in 2026 The Best PostgreSQL Hosting for Developers in 2026 The Best Multi-Region Hosting Platforms in 2026 The Best Platforms to Deploy AI Apps in 2026 (Not the Models, the Apps Around Them) Incident Report: May 19, 2026- GCP Account Suspension Counting to 3 with a new builder processing 50M+ monthly builds Railway iOS preview now available via TestFlight Kill your onboarding: selling to 10,000+ new users a day Your AI wants to nuke your database. Guardrails fix that. Better Rails for Agents: A New Remote MCP and Railway Agent in the CLI Moving Railway's Frontend Off Next.js One command deploys, there's a Stripe APP for that From registrar to deployed: buying a domain inside Railway A letter to open source builders who deserve more Networking is a black box, we used eBPF to open it Heroku Walked So Railway Can Run Security Features Your Security Team Will Love Railway Runs Open Source, Now We're Funding It Railway raises $100M Series B to unburden the builders
Queues on Railway
Faraz Patankar · 2022-09-16 · via Railway Blog

Queues are an asynchronous form of service-to-service communication used to solve various different problems in an elegant way. They’re used to smooth out processing peaks, offload heavy work from one server to many small workers or to buffer and batch work. They’re a common practice once your app reaches a heavy workload.

We have been getting a massive influx of questions revolving around deploying queueing solutions on Railway, and while we don’t have first-party support for a queueing solution, it is straightforward to deploy one using a language-level library.

Examples of such libraries would be Celery for Python, Resque for Ruby, rmq for Go and several other libraries in all the languages we support. In this post, we will go over an example template we created to work with queues in JavaScript using BullMQ and Redis.

BullMQ with BullBoard

Along with using BullMQ and Redis to set up our queueing solution. Additionally, we’ll take advantage of a package called bull-board which is an open-source dashboard built on top of BullMQ. It helps us visualize our queues and provide us with options to retry and clean our jobs.

We will also deploy a Fastify server to serve our dashboard and allow us to add jobs to our queue via an API endpoint.

The Template

Deploy on Railway

Click the button above to deploy your own queue to Railway using our template. We’ll explain how it works as you read the sections below.

The Environment Variables

// env.ts
import { envsafe, port, str } from 'envsafe';

export const env = envsafe({
  REDISHOST: str(),
  REDISPORT: port(),
  REDISUSER: str(),
  REDISPASSWORD: str(),
  PORT: port({
    devDefault: 3000,
  }),
  RAILWAY_STATIC_URL: str({
    devDefault: 'http://localhost:3000',
  }),
});

// queue.ts
const connection: ConnectionOptions = {
  host: env.REDISHOST,
  port: env.REDISPORT,
  username: env.REDISUSER,
  password: env.REDISPASSWORD,
};

The env.ts file specifies the required environment variables all of which are automatically provisioned if you use the template. All the Redis-related variables are then used to establish a connection to the Redis instance in the queue.ts file.

The queue, the board, and the worker

// index.ts
const welcomeEmailQueue = createQueue('WelcomeEmailQueue');

const server: FastifyInstance<Server, IncomingMessage, ServerResponse> =
  fastify();

const serverAdapter = new FastifyAdapter();
createBullBoard({
  queues: [new BullMQAdapter(welcomeEmailQueue)],
  serverAdapter,
});
serverAdapter.setBasePath('/');
server.register(serverAdapter.registerPlugin(), {
  prefix: '/',
  basePath: '/',
});

Next up, we use the BullMQ package to create a new queue called the WelcomeEmailQueue and use the FastifyAdapter to set up our dashboard so we can visualize and monitor what’s going on with our queue.

server.get(
  '/add-job',
  {
    schema: {
      querystring: {
        type: 'object',
        properties: {
          title: { type: 'string' },
          id: { type: 'string' },
        },
      },
    },
  },
  (req: FastifyRequest<{ Querystring: AddJobQueryString }>, reply) => {
    if (
      req.query == null ||
      req.query.email == null ||
      req.query.id == null
    ) {
      reply
        .status(400)
        .send({ error: 'Requests must contain both an id and a email' });

      return;
    }

    const { email, id } = req.query;
    welcomeEmailQueue.add(`WelcomeEmail-${id}`, { email });

    reply.send({
      ok: true,
    });
  }
);

Next, we set up an /add-job endpoint with Fastify to allow us to set up jobs for our worker via an API request. Each request will require the email and id query parameters.

new Worker(
  queueName,
  async (job) => {
    for (let i = 0; i <= 100; i++) {
      await job.updateProgress(i);
      await job.log(`Processing job at interval ${i}`);

      if (Math.random() * 200 < 1) throw new Error(`Random error ${i}`);
    }

    return { jobId: `This is the return value of job (${job.id})` };
  },
  { connection }
);

Lastly, we have a dummy worker that demonstrates job progress and randomly fails jobs so users can experience what a failed job looks like in the dashboard and try out the retry option.

If this were a real-world application, this worker would handle the sending of the welcome email to our users.

The demo project

We have a fully functional live demo of the queue for users to play around with. Here’s a link to the Railway project and the queue dashboard UI. We have an example curl request you can try to experience the dashboard live.

curl https://queue-service-production.up.railway.app/add-job?id=1234&email=hello%40world.com

Conclusion

We hope this post was useful if you were exploring options to deploy a queueing solution on Railway. We have kept the template intentionally simple so it can be extended both in terms of functionality but also to be used with other queueing libraries.

We’d love for the community to contribute more templates and options for our users especially with queueing solutions involving other languages and libraries. If you do end up creating such a template, feel free to reach out to us on Discord as we’d be happy to feature it both on this blog post and our templates page!