---
description: Route KumoMTA log events and queued messages via NATS JetStream, configuring a custom_lua queue handler to publish records to NATS.
---

# Routing Messages via NATS
{{since('2026.03.04-bb93ecb1')}}

In addition to local logging and Webhooks, KumoMTA can relay log events (or
other queued messages) via [NATS JetStream](https://nats.io/).

KumoMTA supports publishing via NATS, using Lua.

The process to queue log events and make them available for sending via
`custom_lua` as a protocol is covered in the [Publishing Log Events Via
Webhooks](../operation/webhooks.md) section of the Operations chapter of the
User Guide.

## Configuring A Queue Handler for NATS

When a message is ready to be queued, the `get_queue_config` event is fired, at
which point you can specify the protocol of the queue, in this case,
`custom_lua`. 

The example below checks whether the message is queued to the `nats` queue and acts accordingly:

```lua
kumo.on('init', function()
  nats = kumo.nats.connect {
    servers = { '127.0.0.1:4222' },
  }
end)

kumo.on('get_queue_config', function(domain, tenant, campaign, routing_domain)
  if domain == 'nats' then
    -- Use the `make.nats` event to handle delivery
    -- of nats log records
    return kumo.make_queue_config {
      protocol = {
        custom_lua = {
          -- this will cause an event called `make.nats` to trigger.
          -- You can pick any name for this event, so long as it doesn't
          -- collide with a pre-defined event, and so long as you bind
          -- to it with a kumo.on call
          constructor = 'make.nats',
        },
      },
    }
  end
  return kumo.make_queue_config {}
end)
```

## Sending Messages via NATS

With the `custom_lua` protocol defined and a custom event trigger declared, the
next step is to catch the `make.nats` event with code that publishes the
message contents via NATS.

The following example publishes the content of the log message via NATS:

```lua
-- This is a user-defined event that matches up to the custom_lua
-- constructor used in `get_queue_config` above.
-- It returns a lua connection object that can be used to "send"
-- messages to their destination. The NATS connection must already
-- have been established in the `init` event.
kumo.on('make.nats', function(domain, tenant, campaign)
  local sender = {}

  -- The send method is called for each log event
  function sender:send(message)
    nats:publish {
      subject = 'subject',
      payload = message:get_data(),
    }
    return '250 ok'
  end

  function sender:close() end

  return sender
end)
```

See the [NATS](../../reference/kumo.nats/index.md) section of the Reference Manual for more information.
