pkey
.Net

RabbitMQ in manufacturing

RabbitMQ in modern manufacturing systems, reliability matters more than raw speed.

Machines generate events continuously:

  • production cycles
  • alarms
  • quality results

If these events are lost, the consequences are real:

  • incorrect production counts
  • broken traceability
  • ERP inconsistencies

This is where RabbitMQ becomes critical.

It introduces event-driven architecture, allowing industrial systems to communicate asynchronously.


Industrial Architecture with RabbitMQ

https://images.openai.com/static-rsc-4/S5vYnWwIDL7hg6H8q4PQ8JbsaaiJbWuoGfiTstvhWV7CzR5C_ulUgbXl7dwHhr5xPgbAEeLH7zi8RZ7_n0YVGOSMbTOO5r0kpssEGnFPiW_1cy8j5kAd6AkHQdFeDPeDxgFfu82ghp15RQeImN0FAhVfygwdxGhE4yTlZMJn734cMya5L4kqVZKuZTe0FZr_?purpose=fullsize
https://images.openai.com/static-rsc-4/h3N0omP_o83lFJQQccMlFYQgrjLXufxzEduH96OtaXF28vazLiTiU2avrrtQ_RG4TwIntSUM3Hg9qtRDb7TnuW_S3fVmECZSF6LUEYtsIpAKl_R4a1QM3tGgdROC50Nto4RXYMpxnhoqyEmFg6YRaCzuIQBlf0OZKm11-vInTMHArK8R74HrIkDeOUTCeAo7?purpose=fullsize
https://images.openai.com/static-rsc-4/PKQDhrwzPTwqgkv7o10knvM2aVJfzNVXPA8heNOu2RhoPY2DcO8CLVMrFRn0pJlckEg6Oq1pvxo52fLrysDkGyxQXjcxM77tNa9NyspudyyYg5ZK4ovmMgwi_Q949VyRxt22d25_aAorYkvIuRvc-kUrOG1ed2YhHW2wqxjybokVoNKM_lA8xGDp8Kb9CNx1?purpose=fullsize

7

Typical production stack:

PLC → OPC UA → .NET Gateway → RabbitMQ → MES → ERP → Cloud

RabbitMQ decouples:

  • machines from MES
  • MES from ERP
  • real-time systems from reporting

Event Flow (Before vs After)

https://images.openai.com/static-rsc-4/Fupm4GcQ0BAHyAv0xvpsQ6ybOLxTtZa_wgzq8u1u7cdrHHonBXEGwlKn3XRhvPOdbrmsMje-MTngt6k-WUrWbpiSXpLu6TqNXlHoi0PXpydKwExW0FbmLev2nlRViVgVimMEtLwpRI-OiThrK4Hsleaw8K_EtlYA1BQeuAXaQr_8924UR9pnl6Smjy_G27ZS?purpose=fullsize
https://images.openai.com/static-rsc-4/6101FHQciGY6k53RwOqLzClCTNwZmkFUZzZvvgNISrKDa6TvPI_BdsMvB7yDVF4J33KgfIj2ON5Z-WqarDwvBAgHwSI-SgEoTLqopldrw8dIXc5FvHNyXdrFiVCNxTrrAg7-NqIkaA3xTX7WJ375X8OzMv9PCUtvmJ6EWU0VlrKdsIbwuHw2TkgY8PxtI9x0?purpose=fullsize
https://images.openai.com/static-rsc-4/vdX7MltRVgvTGGo7vrH6g9C2_98tXe_SHCfp5qxj54Mn5cMgxmQCMKV7P25VQn405NoRrQVNskugaeYhDVRqWajpXINZCLwy9ShPPXK6Qo6FWxoc6pHizpioFnI3-4KQVbVXGtV-xV1yQ-XERJPfTeVmbRNwb_5ANO9ZZOKWvxJ4GqPCS5wboPE33JwBZciL?purpose=fullsize

7

Without RabbitMQ

SCADA → MES → ERP

With RabbitMQ

SCADA → RabbitMQ → MES
PLC → RabbitMQ → Quality
MES → RabbitMQ → ERP


RabbitMQ Concepts

https://images.openai.com/static-rsc-4/cxNFqbIz7gGNBPXu6wlIuZsTUm5_YReLP5UQ1JZ4zwe5oSlOsozl1iiH4UqTG6iiIc9ei6UM5rtNV-MUSfCHAsQPN91ffrKUQjqzgGO-cgkNvxi96j_hKH-dSKJCJiCF1t6NXvpMSebdNf8nh5tMQ_vmyMcWnsAbo0WtGPzBmUaRHem2DKeHo7q8xk_B9gA4?purpose=fullsize
https://images.openai.com/static-rsc-4/lE34l1PUhjusSMbu-TgxqkFSwj56ta1MA9jDMjh9l4N9P6q_qyRM0ODV30Qn9XA4X3178MlVx5DL6z1SWbDUxp9pPYWIxdBuTcyaZdq2vr41h5kvSAIQgJ85E0qYZLlR0xl4xa6IvuVQ3nCkdoMbkXbhEwaGjW4zz5hEjgHt4d29k96x-aMMOVrQIli3bkkj?purpose=fullsize
https://images.openai.com/static-rsc-4/-iFC3mhlxWSe3bgkeuW6_NCGTD7oj2qntO8kd8p1BWtlDvSWXN8-unD0xBEWnNMsOUKkSENxesV-jH-Yl9d-jit74_yCRrwS4Vq9MLpeQjYYGA7cUNeK7phP73QLljrBkGOg6e-0SzkdkyNXQFSvRV40SPhjW1w0KvBiCz4tpeoWlLdYFdrAKi342kjULtrG?purpose=fullsize

8

Core components:

  • Producer
  • Exchange
  • Queue
  • Consumer

Docker Setup

BAT (Batchfile)
docker run -d --hostname rabbit-local --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management

UI:

BAT (Batchfile)
http://localhost:15672

Step 1: Install Package

C#
dotnet add package RabbitMQ.Client

Step 2: Strongly-Typed Event Model

C#
public sealed class MachineCycleCompleted
{
    public Guid EventId { get; init; } = Guid.NewGuid();
    public string MachineId { get; init; } = "";
    public string ProductionOrder { get; init; } = "";
    public DateTime CompletedAtUtc { get; init; } = DateTime.UtcNow;
    public int CycleTimeMs { get; init; }
    public string Result { get; init; } = "";
}

Step 3: Advanced Publisher

C#
using System.Text;
using System.Text.Json;
using RabbitMQ.Client;public sealed class RabbitPublisher : IAsyncDisposable
{
    private readonly IConnection _connection;
    private readonly IChannel _channel;    public RabbitPublisher()
    {
        var factory = new ConnectionFactory { HostName = "localhost" };        _connection = factory.CreateConnectionAsync().GetAwaiter().GetResult();
        _channel = _connection.CreateChannelAsync().GetAwaiter().GetResult();
    }    public async Task PublishAsync<T>(T message, string routingKey)
    {
        await _channel.ExchangeDeclareAsync(
            "manufacturing.events",
            ExchangeType.Topic,
            durable: true);        var json = JsonSerializer.Serialize(message);
        var body = Encoding.UTF8.GetBytes(json);        var props = new BasicProperties
        {
            Persistent = true,
            ContentType = "application/json",
            MessageId = Guid.NewGuid().ToString()
        };        await _channel.BasicPublishAsync(
            exchange: "manufacturing.events",
            routingKey: routingKey,
            basicProperties: props,
            body: body);
    }    public async ValueTask DisposeAsync()
    {
        await _channel.DisposeAsync();
        await _connection.DisposeAsync();
    }
}

Step 4: Producer Example

C#
var publisher = new RabbitPublisher();await publisher.PublishAsync(
    new MachineCycleCompleted
    {
        MachineId = "LINE-01",
        ProductionOrder = "PO-001",
        CycleTimeMs = 5000,
        Result = "OK"
    },
    routingKey: "machine.cycle.completed");

Step 5: Advanced Consumer

C#
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;
using System.Text.Json;var factory = new ConnectionFactory { HostName = "localhost" };var connection = await factory.CreateConnectionAsync();
var channel = await connection.CreateChannelAsync();await channel.QueueDeclareAsync(
    "mes-service",
    durable: true,
    exclusive: false,
    autoDelete: false,
    arguments: new Dictionary<string, object?>
    {
        ["x-dead-letter-exchange"] = "dead-letter"
    });await channel.QueueBindAsync(
    "mes-service",
    "manufacturing.events",
    "machine.cycle.*");await channel.BasicQosAsync(0, 10, false);var consumer = new AsyncEventingBasicConsumer(channel);consumer.ReceivedAsync += async (_, args) =>
{
    try
    {
        var json = Encoding.UTF8.GetString(args.Body.ToArray());        var evt = JsonSerializer.Deserialize<MachineCycleCompleted>(json);        Console.WriteLine($"Processed: {evt?.MachineId}");        await channel.BasicAckAsync(args.DeliveryTag, false);
    }
    catch
    {
        await channel.BasicNackAsync(args.DeliveryTag, false, true);
    }
};
await channel.BasicConsumeAsync("mes-service", false, consumer);

Topic Routing Example

https://images.openai.com/static-rsc-4/cxNFqbIz7gGNBPXu6wlIuZsTUm5_YReLP5UQ1JZ4zwe5oSlOsozl1iiH4UqTG6iiIc9ei6UM5rtNV-MUSfCHAsQPN91ffrKUQjqzgGO-cgkNvxi96j_hKH-dSKJCJiCF1t6NXvpMSebdNf8nh5tMQ_vmyMcWnsAbo0WtGPzBmUaRHem2DKeHo7q8xk_B9gA4?purpose=fullsize
https://images.openai.com/static-rsc-4/ysSQ-TIvwQI3yUXLmfjVx2Hd9Oraq2w4sjAAjx8MgalNRU6Q8r9tyqqFvSdfqhePWfx5oYisoKBwopaq0DK5v8Mh95cBiyTElXBL8IOVH4ooYgSaf-y-A1AFSYwCmN676TSDdK7uzJTKcBHhhyI2UAdF-KZDYsTizdbHRsSonVmmAyGAVK3VG9RgEuHvQsnG?purpose=fullsize
https://images.openai.com/static-rsc-4/6101FHQciGY6k53RwOqLzClCTNwZmkFUZzZvvgNISrKDa6TvPI_BdsMvB7yDVF4J33KgfIj2ON5Z-WqarDwvBAgHwSI-SgEoTLqopldrw8dIXc5FvHNyXdrFiVCNxTrrAg7-NqIkaA3xTX7WJ375X8OzMv9PCUtvmJ6EWU0VlrKdsIbwuHw2TkgY8PxtI9x0?purpose=fullsize

5

Routing keys:

C#
machine.cycle.completed
machine.alarm.raised
quality.inspection.completed
erp.order.started

Reliability Layer

https://images.openai.com/static-rsc-4/Vie9QPvR57evT01TYhruyxlJsB8Ha89bgyUkL2RI_5dER4Zw37hPf4esob1G--EnFQ-QyVoWymyn19SBTu9j1_LeMlHriJrcCBBpzA2VaUyALIp4UVvauYL2xoEhG-UP4AExjC2pAQ7WmSQnG3InyLsrUNlL2nKAg0mqrPeCExHlMcAUiH3zotxIfCMGYETB?purpose=fullsize
https://images.openai.com/static-rsc-4/JjEQW33xTE23z7VS4GYE-g9crGDNXm4TD4UjQTQ9NrYDaKT1z6akPzDMShMK-5rPaShlmCqiLzfjCuF6f9hpQdZH4ytFyaxKOCqcpCXL-RbuimsMh4wW7Z3Ssq3J2wZ6mdwTg3D5b3pdgKUWzhTyydvLbhTvijMyh1TuRTvq4kZhjNHMiYwTPjMKsESMaupa?purpose=fullsize
https://images.openai.com/static-rsc-4/KXt9QgesMgZqqQ739FijVk0jpbn9TX4mFT5szYusiVY1kFk_49FkM4p7_vE7ADyyMWM8I2fZlsKOd3CBu4u6TKphg-jxpMU4ebRjsq-dOSMO56LuNS_FXblMhwIZdzkexVl_QSgKoy970x0ZBvLKzFkBeQvaTTuebSc8y4d47hzEeawv3jVJVPTqjGiKIvxL?purpose=fullsize

7

Key mechanisms:

C#
await channel.BasicAckAsync(tag, false);
await channel.BasicNackAsync(tag, false, true);

Outbox Pattern (C#)

https://images.openai.com/static-rsc-4/yDxRfOJp-JpverMw-98HJfgiSfweucHuaO7i9GmJDMnHfD94Sy8vJfV0EwxNBVMt3jgTp9ul6ODM-hzfLEH9Hm8EFMX3HxUlB6edSIorjb8rfB7Y3DIta_t--YzQUqiSdljR-0rpLk__fgC-L9tQAYWup7pRnr4xEp-D1QPiQtrdOAOD5QNneMBM-ONn7Rp9?purpose=fullsize
https://images.openai.com/static-rsc-4/qC7wf8TH-ZLWCWpqOetZCAyapO7pi-FVPDtVxkId_WT-3io7ND5k9F4rYgwC7_OwDhH-5htOVFJe39zFP8-aDvkq5iLd94gjOcvKtRNH6JwoVJVWZ0gvOWmTAJ8t99IZwPz8fvTNiId5nkiSMiiBUUsch_criB-WsOojTQvtR0vJwSk7_ncZXxD58hK04yaJ?purpose=fullsize
https://images.openai.com/static-rsc-4/J5KdtHWzXZkA8n-SV62EcxtgYBU6oxJtYfr5eDqyflCIOBoflmA3QIyRWbMZfUJDzX1wxIeJYbbjGq4KfbgS4KxC9YoOrwIAtL8UMnsPCRv0hIbw1pgDIs0xx4HQ9akp-8Ab0oslxRQMpKYnpAwz1FRDdo3bIxHDx5b_rj6-qAliNfoBJXQq6lWrmzMKjoLN?purpose=fullsize

7

C#
public class OutboxMessage
{
    public Guid Id { get; set; }
    public string Payload { get; set; } = "";
    public DateTime Created { get; set; }
    public DateTime? Processed { get; set; }
}

Publisher worker:

C#
while(true)
{
    var messages = db.Outbox.Where(x => x.Processed == null).ToList();    foreach(var m in messages)
    {
        await publisher.PublishAsync(m.Payload, "machine.cycle.completed");
        m.Processed = DateTime.UtcNow;
    }    await db.SaveChangesAsync();
    await Task.Delay(2000);
}

Idempotent Consumer

C#
if(db.Processed.Any(x => x.Id == evt.EventId))
{
    await channel.BasicAckAsync(tag, false);
    return;
}

Best Practices

  • Always use durable queues
  • Always use persistent messages
  • Always use manual ACK
  • Use topic exchanges
  • Implement retry + DLQ
  • Use outbox pattern

Conclusion

RabbitMQ is not just infrastructure.

In manufacturing, it is:

  • a reliability layer
  • a scalability enabler
  • a system decoupler

Combined with .NET, it creates a robust industrial integration platform.


References

https://www.rabbitmq.com/
https://opcfoundation.org/
https://support.industry.siemens.com/cs/document/42014088/programming-an-opc-ua-.net-client-with-c-for-the-simatic-net-opc-ua-server?lc=en-ru

More Info

We implement this in real production systems.
If you need help → contact us

Contact