1. Losing nothing: the persistent queue #
Memory or disk.
The problem #
By default, Logstash keeps in-flight events in an in-memory queue (queue.type: memory): a crash loses them. The persistent queue (PQ) writes them to disk between inputs and filters: they survive a restart and absorb spikes when Elasticsearch slows down.
Configuration #
# config/pipelines.yml
- pipeline.id: web
path.config: /usr/share/logstash/pipeline/web.conf
queue.type: persisted
queue.max_bytes: 4gb # au-delà : contre-pression vers les inputs
path.queue: /var/lib/logstash/queue
dead_letter_queue.enable: true| Setting | Default | Role |
|---|---|---|
| queue.type | memory | memory or persisted |
| queue.max_bytes | 1024mb | maximum size on disk |
| queue.page_capacity | 64mb | page file size |
| queue.checkpoint.writes | 1024 | checkpoint frequency |
Common mistake: Believing the PQ protects against everything: it replaces neither reliable storage nor a sender able to retry. A UDP input (syslog) still loses whatever arrives during downtime; put Kafka in front if loss is unacceptable.
Good practice: Delivery is "at least once": after a recovery, an event may be indexed twice. Compute a stable ID (fingerprintfilter) and pass it asdocument_idto make writes idempotent.
2. The dead letter queue #
Keeping rejections.
Principle #
When Elasticsearch rejects a document (400 or 404 error, typically a mapping conflict), the elasticsearch output writes it to the DLQ instead of dropping it, along with the reason. You then fix and replay it.
# Pipeline de reprise : lit la DLQ du pipeline « web »
input {
dead_letter_queue {
path => "/usr/share/logstash/data/dead_letter_queue"
pipeline_id => "web"
commit_offsets => true
}
}
filter {
# la raison du rejet : [@metadata][dead_letter_queue][reason]
mutate { convert => { "status" => "integer" } }
}
output { elasticsearch { hosts => ["http://elasticsearch:9200"] data_stream => true } }| Setting | Role |
|---|---|
| dead_letter_queue.enable | enables the DLQ (per pipeline) |
| dead_letter_queue.max_bytes | maximum size (1024mb by default) |
| dead_letter_queue.storage_policy | drop_newer or drop_older when full |
| dead_letter_queue.retain.age | retention period (e.g. 7d) |
Good to know: Only "permanent" rejections go to the DLQ; transient errors (429, 503) are retried indefinitely by the output: backpressure then protects the data.
3. Multiple pipelines #
Isolating flows.
pipelines.yml #
A single large pipeline mixes flows: one slow filter or failing output blocks everything. pipelines.yml declares several independent pipelines, each with its own workers, queue and configuration.
- pipeline.id: entree
config.string: |
input { beats { port => 5044 } }
output {
if [event][dataset] == "nginx.access" { pipeline { send_to => ["web"] } }
else if [event][category] == "authentication" { pipeline { send_to => ["securite"] } }
else { pipeline { send_to => ["autres"] } }
}
- pipeline.id: web
path.config: /etc/logstash/conf.d/web.conf # input { pipeline { address => "web" } }
pipeline.workers: 4
- pipeline.id: securite
path.config: /etc/logstash/conf.d/securite.conf
queue.type: persisted| Pattern | Use |
|---|---|
| Distributor | one input, one pipeline per data type |
| Output isolator | a slow output (S3 archive) does not block Elasticsearch: each has its pipeline and PQ |
| Forked path | the same event processed differently for two destinations |
| Collector | several pipelines converge on a shared output |
4. Performance #
Workers, batches, JVM.
Settings #
| Setting | Default | Advice |
|---|---|---|
| pipeline.workers | number of cores | increase if CPU is underused and filters are costly |
| pipeline.batch.size | 125 | 250 to 1000 for more efficient Elasticsearch outputs (more memory) |
| pipeline.batch.delay | 50 ms | rarely changed |
| jvm.options (-Xms / -Xmx) | 1g | identical, 4 to 8 GB is usually enough |
curl -s localhost:9600/_node/stats/pipelines?pretty | jq '.pipelines.web.events'
curl -s localhost:9600/_node/hot_threads?human=true | head -40Good practice: Measure before tuning: compareevents.in,events.outand per-filterduration_in_millisin_node/statsto find the costly filter.
My progress
Sign in to track your progress and take notes. Sign in
💬 Questions about this lesson
No questions yet: be the first to ask for help or share your configuration.
Course Glossary
Logstash
An open-source, server-side data processing pipeline that ingests data from a multitude of sources simultaneously, transforms it, and then sends it to...
Recommended Articles
Logstash best practices: pipelines, performance, reliability and monitoring
Logstash best practices: multiple pipelines, dissect rather than grok, conditionals, persistent q...
Logstash: enrich, test, monitor and deploy on Kubernetes
Enrich with translate, geoip and elasticsearch, consume Kafka, test pipelines, monitor Logstash a...
Logstash: role, pipeline concept and installation
Written version of the video lessons: what Logstash is for, how a pipeline works (inputs, filters...
Other log sources and queues: syslog, Fluent Bit, Kafka, Redis
Written version of the video lessons: collect syslog, Fluent Bit and other sources, then insert a...
Logstash: managing plugins and adopting Elastic Common Schema (ECS)
Written version of the video lessons: list, install, update and bundle Logstash plugins offline; ...
Logstash: inputs and outputs
Written version of the video lessons: common inputs (beats, file, tcp/udp, http, kafka, jdbc) and...
Logstash: filters, grok and dissect
Written version of the video lessons: essential filters (mutate, date, json, kv, drop), the grok ...
Elasticsearch on Kubernetes with ECK: deployment, persistent storage and upgrades
Deploy Elasticsearch and Kibana on Kubernetes with Elastic Cloud on Kubernetes (ECK): operator, E...
Machine learning in Elastic: anomaly detection and AIOps
Automatically detect abnormal behaviour: anomaly detection jobs, datafeeds, detectors, influencer...