> For the complete documentation index, see [llms.txt](https://docs.valtimo.nl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.valtimo.nl/v12/features/outbox/for-developers.md).

# For developers

{% hint style="info" %}
The for developers section within each feature gives more tech heavy information of configuring, extending or altering Valtimo via the codebase.
{% endhint %}

<details>

<summary>Custom outbox message publisher</summary>

**Creating a custom outbox message publisher**

Valtimo offers the functionality needed to create and add custom outbox message publishers to Valtimo implementations. This is useful when the desired message broker (middleware) is not provided by Valtimo out of the box or by a third party.

Implementing a custom message publisher only requires work in the backend.

**Dependencies**

To create a custom message publisher in your project, the following dependency is needed:

```kotlin
    api("com.ritense.valtimo:outbox:$valtimoVersion") 
```

**Considerations**

The outbox pattern is designed to guarantee reliable (at least once) delivery.

Because of that, it is important to make sure messages are received by the broker when publishing. This can often be done by checking the response when it's a synchronous operation, or awaiting a response on an asynchronous channel.

Please refer to the documentation of your message broker and client. If message delivery cannot be guaranteed, consider using a different solution.

**Implementing the MessagePublisher**

The custom message publisher should implement the `com.ritense.outbox.publisher.MessagePublisher` interface from the `outbox` module:

```kotlin
class CustomMessagePublisher : MessagePublisher {

    override fun publish(message: OutboxMessage) {
        TODO("Send message to broker")
    }
}
```

When delivery fails or acknowledgement takes too long, a `MessagePublishingFailed` or a (subclass of) `RuntimeException` should be thrown to stop the transaction and keep the outbox message in the database for a retry later on.

When delivery is successful (no exceptions are thrown), the outbox message will be deleted from the outbox table automatically.

**Batch publishing**

The `MessagePublisher` interface also provides a `publishBatch` method that receives a list of messages and returns per-message results. The default implementation calls `publish()` for each message individually, catching exceptions per message.

Publishers that support native batch operations (e.g. sending multiple messages in a single HTTP POST or pipelining broker confirms) can override `publishBatch` for improved throughput:

```kotlin
class CustomBatchMessagePublisher : MessagePublisher {

    override fun publish(message: OutboxMessage) {
        val result = publishBatch(listOf(message)).first()
        if (!result.success) {
            throw result.error ?: MessagePublishingFailed("Failed to publish message ${message.id}")
        }
    }

    override fun publishBatch(messages: List<OutboxMessage>): List<MessagePublishResult> {
        // Send all messages in a single batch operation
        val response = batchSend(messages)

        // Return per-message results
        return messages.zip(response.results).map { (message, result) ->
            MessagePublishResult(
                messageId = message.id,
                success = result.isSuccess,
                error = result.error
            )
        }
    }
}
```

Successfully published messages are deleted from the outbox. Failed messages remain in the outbox table and will be retried in the next poll cycle.

**Bean configuration**

The custom message publisher should be configured as a Bean in the Spring application.

```kotlin
@Configuration
@ConditionalOnOutboxEnabled // This will disable the bean creation when `valtimo.outbox.enabled` is set to false
class CustomMessagePublisherAutoconfiguration {

    @Bean
    @ConditionalOnMissingBean(MessagePublisher::class)
    fun customMessagePublisher(): MessagePublisher {
        return CustomMessagePublisher()
    }
}
```

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.valtimo.nl/v12/features/outbox/for-developers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
