Skip to content

Widhian Bramantya

coding is an art form

Menu
  • About Me
Menu
rabbitmq

Reliable Messaging with RabbitMQ: Acknowledgments, Durability, and Persistence

Posted on September 8, 2025September 8, 2025 by admin

3. Persistence

What it is

Persistence means the messages inside the queue are saved to disk, not just memory.

  • Without persistence: If RabbitMQ crashes, all in-memory messages are lost.
  • With persistence: Messages are stored on disk and survive a restart.

Example

Goal: Ensure messages survive a broker restart by combining durable queue + persistent messages.

// persistence_example.go
package main

import (
	"log"

	amqp "github.com/rabbitmq/amqp091-go"
)

func mustConn() *amqp.Connection {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	if err != nil { log.Fatal(err) }
	return conn
}

func main() {
	conn := mustConn()
	defer conn.Close()

	ch, err := conn.Channel()
	if err != nil { log.Fatal(err) }
	defer ch.Close()

	// Durable queue
	q, err := ch.QueueDeclare(
		"orders_queue_persist",
		true,  // durable
		false, // autoDelete
		false, // exclusive
		false, // noWait
		nil,
	)
	if err != nil { log.Fatal(err) }

	// Publish a persistent message
	if err := ch.Publish(
		"",
		q.Name,
		false, false,
		amqp.Publishing{
			DeliveryMode: amqp.Persistent, // <--- persisted to disk
			ContentType:  "text/plain",
			Body:         []byte("Order #999 created"),
		},
	); err != nil {
		log.Fatal(err)
	}

	log.Println("persistent message published to a durable queue (message survives restarts)")
}

Optional: Publisher Confirms (extra safety for producers)

If you also want the producer to know the broker safely received the message:

// publisher_confirms.go
package main

import (
	"log"

	amqp "github.com/rabbitmq/amqp091-go"
)

func mustConn() *amqp.Connection {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	if err != nil { log.Fatal(err) }
	return conn
}

func main() {
	conn := mustConn()
	defer conn.Close()

	ch, err := conn.Channel()
	if err != nil { log.Fatal(err) }
	defer ch.Close()

	if err := ch.Confirm(false); err != nil { log.Fatal(err) }
	acks := ch.NotifyPublish(make(chan amqp.Confirmation, 1))

	q, _ := ch.QueueDeclare("orders_queue_confirm", true, false, false, false, nil)

	if err := ch.Publish("", q.Name, false, false, amqp.Publishing{
		DeliveryMode: amqp.Persistent,
		Body:         []byte("Order with confirm"),
	}); err != nil {
		log.Fatal(err)
	}

	confirm := <-acks
	if !confirm.Ack {
		log.Fatal("publish NOT confirmed by broker")
	}
	log.Println("publish confirmed by broker")
}

Notes

  • Install the driver: go get github.com/rabbitmq/amqp091-go
  • Run RabbitMQ locally (e.g., Docker):
    docker run -p 5672:5672 -p 15672:15672 rabbitmq:3-management
  • Combine durable queues + persistent messages + manual ACKs for end-to-end reliability.
See also  Understanding RabbitMQ Exchange Types with Go: Default, Direct, Fanout, and Topic

How to enable

  • Mark messages as persistent when publishing.
  • Example in code (pseudocode):
    • channel.publish("exchange", "routing_key", Buffer.from("msg"), { persistent: true });

4. How They Work Together

For full reliability, you need all three:

  1. Durable queues – so the queue is still there after restart.
  2. Persistent messages – so messages inside the queue survive restart.
  3. Acknowledgments – so RabbitMQ only removes messages after the consumer confirms.

Note: Even with persistence, there is a small chance of data loss if RabbitMQ crashes before flushing to disk. For very critical systems, you may also use Publisher Confirms (RabbitMQ feature that tells the producer when a message is safely stored).

5. Best Practices

  • Use manual ACKs to avoid losing messages during crashes.
  • Make queues durable if they handle important data.
  • Mark important messages as persistent.
  • Combine with Publisher Confirms for end-to-end safety.
  • Monitor queues to avoid overload (too many persistent messages can slow down the system).

Conclusion

Reliability is a key strength of RabbitMQ. By using acknowledgments, durability, and persistence, you can make sure messages are delivered safely, even if consumers fail or servers restart. These features make RabbitMQ a trusted backbone for critical applications such as payments, orders, and IoT systems.

Pages: 1 2 3
Category: RabbitMQ

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Linkedin

Widhian Bramantya

Recent Posts

  • Log Management at Scale: Integrating Elasticsearch with Beats, Logstash, and Kibana
  • Index Lifecycle Management (ILM) in Elasticsearch: Automatic Data Control Made Simple
  • Blue-Green Deployment in Elasticsearch: Safe Reindexing and Zero-Downtime Upgrades
  • Maintaining Super Large Datasets in Elasticsearch
  • Elasticsearch Best Practices for Beginners
  • Implementing the Outbox Pattern with Debezium
  • Production-Grade Debezium Connector with Kafka (Postgres Outbox Example – E-Commerce Orders)
  • Connecting Debezium with Kafka for Real-Time Streaming
  • Debezium Architecture – How It Works and Core Components
  • What is Debezium? – An Introduction to Change Data Capture
  • Offset Management and Consumer Groups in Kafka
  • Partitions, Replication, and Fault Tolerance in Kafka
  • Delivery Semantics in Kafka: At Most Once, At Least Once, Exactly Once
  • Producers and Consumers: How Data Flows in Kafka
  • Kafka Architecture Explained: Brokers, Topics, Partitions, and Offsets
  • Getting Started with Apache Kafka: Core Concepts and Use Cases
  • Security Best Practices for RabbitMQ in Production
  • Understanding RabbitMQ Virtual Hosts (vhosts) and Their Uses
  • RabbitMQ Performance Tuning: Optimizing Throughput and Latency
  • High Availability in RabbitMQ: Clustering and Mirrored Queues Explained

Recent Comments

  1. Playing with VPC AWS (Part 2) – Widhian's Blog on Playing with VPC AWS (Part 1): VPC, Subnet, Internet Gateway, Route Table, NAT, and Security Group
  2. Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh – Widhian's Blog on Basic Concept of ElasticSearch (Part 1): Introduction
  3. Basic Concept of ElasticSearch (Part 2): Architectural Perspective – Widhian's Blog on Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh
  4. Basic Concept of ElasticSearch (Part 3): Translog, Flush, and Refresh – Widhian's Blog on Basic Concept of ElasticSearch (Part 2): Architectural Perspective
  5. Basic Concept of ElasticSearch (Part 1): Introduction – Widhian's Blog on Basic Concept of ElasticSearch (Part 2): Architectural Perspective

Archives

  • October 2025
  • September 2025
  • August 2025
  • November 2021
  • October 2021
  • August 2021
  • July 2021
  • June 2021
  • March 2021
  • January 2021

Categories

  • Debezium
  • Devops
  • ElasticSearch
  • Golang
  • Kafka
  • Lua
  • NATS
  • Programming
  • RabbitMQ
  • Redis
  • VPC
© 2025 Widhian Bramantya | Powered by Minimalist Blog WordPress Theme