ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

Leader Election

Designate a single node — re-designable in seconds — to do what several should not do simultaneously.

Problem

A service runs in N instances for HA, but some tasks must have only one executor at time T: cron poller, scheduler, sequential channel processor. If every instance runs in parallel, you get either duplication (sending the invoice 5 times) or corruption (two nodes reordering the same outbox).

Forces

  • A crashed instance must hand off its role quickly (else the task is suspended).
  • No node should believe it's the leader while another already is (split brain).
  • Too-frequent elections create flapping and unnecessary latency.
  • Heartbeat-based failure detection must be faster than the business tolerance window.

Solution

Use a coordination service (ZooKeeper, etcd, Consul, or Kubernetes Lease ConfigMap) where each candidate tries to take a lease with TTL. The lease holder is leader; it must renew before expiration. Others observe: if the lease expires (the leader is dead or unreachable), the first candidate to claim the lease becomes leader. Raft (etcd) and ZAB (ZooKeeper) algorithms handle registry consistency. For simple cases, a SELECT ... FOR UPDATE on a dedicated row in DB suffices (Postgres advisory lock).

Structure

Coordination service (etcd / ZooKeeper)
       lease key: "edi.outbox.poller.leader"
                  │
   ┌──────────────┼──────────────┐
   ▼              ▼              ▼
 Node A         Node B         Node C
 (current      (observer)    (observer)
  leader)
   │
   │ renew lease every 5s (TTL 15s)
   │
   X dies (network partition)
                  │
        lease TTL expires 15s later
                  │
        Node B acquires lease ──► becomes leader

EDI implementation

A 3-replica EDI hub needs to designate one node for: (1) polling AS2 MDNs — else two nodes would process the same MDN and mark the order "delivered" twice; (2) generate the end-of-day report sent to the manager; (3) purge the outbox table. Simple implementation: a Kubernetes Lease edi-mdn-poller with 30 s retention, renewed every 10 s by the leader. On node crash, another takes the lease in under a minute.

Anti-patterns

  • TTL too long — a dead node blocks the task for minutes.
  • No fencing token — a former leader woken after a partition keeps writing and corrupts state.
  • Election on a single-instance coordination service — it becomes a SPOF.
  • Leader that doesn't stop the task when it loses the lease — split brain guaranteed.
  • Lease renewal interrupted by a Java GC pause — leader loses lease without knowing it's "dead".

Sources