# How to Configure Block Production Timings in Fuel Core's PoA Module

> Learn how to configure block production timings in Fuel Core's PoA module using the Trigger enum and CLI flags. Optimize your Fuel network efficiency today.

- Repository: [Fuel Labs/fuel-core](https://github.com/FuelLabs/fuel-core)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Fuel Core's Proof-of-Authority (PoA) module uses a `Trigger` enum with four variants—`Instant`, `Never`, `Interval`, and `Open`—to control when blocks are produced, configured via CLI flags in [`bin/fuel-core/src/cli/run/consensus.rs`](https://github.com/FuelLabs/fuel-core/blob/main/bin/fuel-core/src/cli/run/consensus.rs) and processed in [`crates/services/consensus_module/poa/src/service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/service.rs).**

Block production timings in the FuelLabs/fuel-core repository are governed by the consensus module's configuration system. The PoA service relies on a `Trigger` enum defined in [`crates/services/consensus_module/poa/src/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/config.rs) to determine exactly when to seal new blocks. Understanding these triggers allows node operators to optimize their block production strategy for different network conditions.

## Understanding the PoA Trigger Enum

The `Trigger` enum in [`crates/services/consensus_module/poa/src/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/config.rs) defines four distinct block production strategies:

- **`Instant`** – Produces a block immediately when the transaction pool receives new transactions. This minimizes latency but may result in smaller blocks.
- **`Never`** – Disables block production entirely. The node operates as a passive listener, syncing blocks from other producers without creating its own.
- **`Interval { block_time }`** – Produces blocks at fixed time intervals regardless of transaction activity. The `block_time` parameter specifies the duration between blocks.
- **`Open { period }`** – Opens a block production window immediately and keeps it open for the specified `period`. The block is sealed when the period expires, allowing transaction accumulation during the window.

## CLI Configuration for Block Production Timings

Node operators configure block production timings through command-line arguments defined in [`bin/fuel-core/src/cli/run/consensus.rs`](https://github.com/FuelLabs/fuel-core/blob/main/bin/fuel-core/src/cli/run/consensus.rs). The `PoATriggerArgs` struct parses these flags and converts them into the `Trigger` enum.

The available CLI flags map to trigger variants as follows:

- `--poa-instant` – When set to `true` (default), enables `Trigger::Instant`. When set to `false`, falls through to `Trigger::Never`.
- `--poa-interval-period <duration>` – Activates `Trigger::Interval` with the specified block time (e.g., `5s` for 5 seconds).
- `--poa-open-period <duration>` – Activates `Trigger::Open` with the specified window duration.

Clap's `ArgGroup` enforcement in [`bin/fuel-core/src/cli/run/consensus.rs`](https://github.com/FuelLabs/fuel-core/blob/main/bin/fuel-core/src/cli/run/consensus.rs) ensures that only one mode (instant, interval, or open) can be active simultaneously.

## How the PoA Service Schedules Block Production

The PoA service implementation in [`crates/services/consensus_module/poa/src/service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/service.rs) consumes the `Trigger` configuration to schedule block production through two primary functions: `next_time` and `run`.

### Calculating Next Block Time

The `next_time` function calculates the timestamp for the next block based on the trigger variant:

```rust
// From crates/services/consensus_module/poa/src/service.rs
match self.trigger {
    Trigger::Interval { block_time } => {
        increase_time(self.last_timestamp, block_time)
    }
    Trigger::Open { period } => {
        increase_time(self.last_timestamp, period)
    }
    // Instant and Never variants handled separately
}

```

For `Interval` triggers, it adds the configured `block_time` to the last timestamp. For `Open` triggers, it adds the `period` to determine when the window closes.

### Scheduling Production Futures

The `run` function builds a `next_block_production` future that determines when to attempt block creation:

```rust
// From crates/services/consensus_module/poa/src/service.rs
let next_block_production: NextBlockProduction = match self.trigger {
    Trigger::Instant => Box::pin(async {
        let _ = self.new_txs_watcher.changed().await;
        Instant::now()
    }),
    Trigger::Interval { block_time } => {
        // Sleep until last_block_created + block_time
        Box::pin(async move {
            sleep_until(next_block_time).await;
            Instant::now()
        })
    }
    Trigger::Open { period } => {
        // Deadline is last_block_created + period
        Box::pin(async move { deadline })
    }
    Trigger::Never => Box::pin(std::future::pending()),
};

```

- **Instant**: Waits for transaction pool changes via `new_txs_watcher.changed()`.
- **Interval**: Sleeps until the next interval boundary.
- **Open**: Returns the deadline immediately; the block is produced when the period expires.
- **Never**: Returns a pending future that never resolves.

## Additional Timing Configuration Parameters

Beyond the trigger mechanism, the PoA `Config` struct in [`crates/services/consensus_module/poa/src/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/config.rs) includes several timeout parameters that affect block production:

- **`production_timeout`** – Maximum duration allowed for the block producer to finish before the task aborts. Defaults to 20 seconds (`Duration::from_secs(20)`).
- **`time_until_synced`** – Duration the node waits for the network to be considered "synced" before starting production. Defaults to `Duration::ZERO`.
- **`min_connected_reserved_peers`** – Minimum number of reserved peers required before the PoA task can start. Defaults to `0`.

These values propagate from the global service configuration in [`crates/fuel-core/src/service/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/fuel-core/src/service/config.rs) when the node initializes.

## Practical Configuration Examples

### Command-Line Examples

Configure instant mode (default behavior):

```bash
fuel-core run

```

Configure fixed 5-second block intervals:

```bash
fuel-core run --poa-interval-period=5s

```

Configure a 30-second open production window:

```bash
fuel-core run --poa-open-period=30s

```

Disable block production (listener mode):

```bash
fuel-core run --poa-instant=false

```

### Programmatic Configuration

Create a custom PoA configuration in Rust:

```rust
use fuel_core_services::consensus_module::poa::{Config, Trigger};
use fuel_core_types::signer::SignMode;
use tokio::time::Duration;

// Configure interval mode with 10-second blocks
let poa_cfg = Config {
    trigger: Trigger::Interval { 
        block_time: Duration::from_secs(10) 
    },
    signer: SignMode::Unavailable, // Use a real key for production
    metrics: false,
    min_connected_reserved_peers: 0,
    time_until_synced: Duration::ZERO,
    production_timeout: Duration::from_secs(30),
    chain_id: Default::default(),
};

```

Inspect the active trigger at runtime:

```rust
match self.trigger {
    Trigger::Instant => tracing::info!("Instant mode – producing on Tx arrival"),
    Trigger::Never   => tracing::info!("Never mode – not producing blocks"),
    Trigger::Interval { block_time } => {
        tracing::info!("Interval mode: {} s", block_time.as_secs())
    }
    Trigger::Open { period } => {
        tracing::info!("Open mode: {} s", period.as_secs())
    }
}

```

## Summary

- Fuel Core's PoA module uses a **`Trigger`** enum with four variants (`Instant`, `Never`, `Interval`, `Open`) to control block production timings.
- Configuration originates in **[`bin/fuel-core/src/cli/run/consensus.rs`](https://github.com/FuelLabs/fuel-core/blob/main/bin/fuel-core/src/cli/run/consensus.rs)** and is defined structurally in **[`crates/services/consensus_module/poa/src/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/config.rs)**.
- The PoA service in **[`crates/services/consensus_module/poa/src/service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/service.rs)** implements the scheduling logic via `next_time()` for timestamp calculation and `run()` for future-based production triggers.
- Additional timing parameters include **`production_timeout`** (default 20s), **`time_until_synced`**, and **`min_connected_reserved_peers`**.
- Only one trigger mode can be active at a time, enforced by CLI argument groups.

## Frequently Asked Questions

### What is the default block production mode in Fuel Core?

By default, Fuel Core runs in **Instant** mode (`--poa-instant=true`), meaning the node produces a new block immediately whenever the transaction pool receives new transactions. This minimizes latency but may result in smaller, more frequent blocks compared to fixed-interval production.

### How do I configure Fuel Core to produce blocks at fixed time intervals?

Use the `--poa-interval-period` flag with a duration string (e.g., `5s`, `1m`). This activates `Trigger::Interval`, causing the PoA service to sleep until `last_block_created + block_time` before producing each new block, regardless of transaction activity. Note that you cannot use this flag simultaneously with `--poa-instant` or `--poa-open-period` due to CLI group constraints.

### What happens if block production takes longer than the configured timeout?

If block production exceeds the **`production_timeout`** duration (default 20 seconds), the PoA task aborts the current production attempt. This timeout is defined in [`crates/services/consensus_module/poa/src/config.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/config.rs) and propagated from the global service configuration. Operators can adjust this value programmatically via the `Config` struct if running Fuel Core as a library.

### Can I disable block production entirely while still syncing the network?

Yes. Set `--poa-instant=false` to activate `Trigger::Never`, or simply omit any production flags and set `--poa-instant` to false. In this mode, the node operates as a passive listener, syncing blocks from peers without producing its own. The `run()` function in [`crates/services/consensus_module/poa/src/service.rs`](https://github.com/FuelLabs/fuel-core/blob/main/crates/services/consensus_module/poa/src/service.rs) returns a pending future that never resolves, effectively disabling the production loop.