Skip to main content

Fast Blocks

Cardano DevKit supports sub-second block times (100-200ms) for rapid development iteration.

Why Fast Blocks?

Standard TestnetLocal Devnet (Fast)
20 second blocks100ms blocks
40 seconds to confirm200ms to confirm
3 transactions = 1 minute3 transactions = 600ms

Development speed increase: 100x+

Configuring Block Time

Via CLI

# 100ms blocks (fastest)
npx cardano-devkit start --block-time 100

# 200ms blocks (recommended)
npx cardano-devkit start --block-time 200

# 500ms blocks (balanced)
npx cardano-devkit start --block-time 500

Via Code

const devnet = createDevnetManager({
blockTimeMs: 200, // milliseconds
slotLength: 0.2 // seconds (should match)
});

await devnet.start();

How It Works

The local devnet modifies the Cardano node's genesis parameters:

{
"slotLength": 0.2,
"activeSlotsCoeff": 1.0,
"securityParam": 2
}
  • slotLength: Time per slot in seconds
  • activeSlotsCoeff: Probability of block production (1.0 = every slot)
  • securityParam: Blocks needed for finality (reduced for speed)

Block Time vs Slot Length

Block Time (ms)Slot Length (s)Use Case
1000.1Maximum speed, single dev
2000.2Fast development
5000.5Team development
10001.0Default, stable
2000020.0Testnet simulation

Performance Considerations

CPU Usage

Fast blocks increase CPU usage:

Block TimeRelative CPU
1000ms1x (baseline)
500ms2x
200ms5x
100ms10x

Recommendations

// Development machine
const devnet = createDevnetManager({
blockTimeMs: 200 // Good balance
});

// CI/CD pipeline
const devnet = createDevnetManager({
blockTimeMs: 500 // More stable
});

// Presentation/demo
const devnet = createDevnetManager({
blockTimeMs: 1000 // Lower resource usage
});

Transaction Timing

With fast blocks, you can iterate rapidly:

// Build and submit
const tx1 = await lucid.newTx()
.pay.ToAddress(addr, { lovelace: 5_000_000n })
.complete();
const signed1 = await tx1.sign.withWallet().complete();
const hash1 = await signed1.submit();

// Wait for confirmation (200ms with fast blocks!)
await lucid.awaitTx(hash1);

// Immediately use the output
const tx2 = await lucid.newTx()
.pay.ToAddress(addr2, { lovelace: 4_000_000n })
.complete();
// ...

Monitoring Block Production

Via CLI

# Watch block production
npx cardano-devkit tip --watch

# Output:
# Slot: 1234 | Block: 1234 | Time: 246.8s
# Slot: 1235 | Block: 1235 | Time: 247.0s
# ...

Via WebSocket

const ws = new WebSocket('ws://localhost:10080/ws');

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'block') {
console.log(`New block: ${data.height} at slot ${data.slot}`);
}
};

Via API

const devnet = createDevnetManager();

// Poll for new blocks
setInterval(async () => {
const tip = await devnet.getTip();
console.log(`Slot: ${tip.slot}, Height: ${tip.height}`);
}, 200);

Best Practices

1. Match Slot Length to Block Time

// ✅ Correct
const devnet = createDevnetManager({
blockTimeMs: 200,
slotLength: 0.2
});

// ❌ Incorrect - mismatched
const devnet = createDevnetManager({
blockTimeMs: 200,
slotLength: 1.0 // Will cause timing issues
});

2. Use Appropriate Timeouts

// Standard timeout for 200ms blocks
const TX_TIMEOUT = 5000; // 5 seconds = ~25 blocks

async function submitWithTimeout(tx: Transaction) {
const hash = await tx.submit();

const confirmed = await Promise.race([
lucid.awaitTx(hash),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), TX_TIMEOUT)
)
]);

return hash;
}

3. Handle Block Reorgs (Rare)

// With fast blocks, minor reorgs are possible
// Wait for a few confirmations for critical operations

async function waitForConfirmations(txHash: string, confirmations = 3) {
await lucid.awaitTx(txHash);

// Wait for additional blocks
const devnet = createDevnetManager();
const initialTip = await devnet.getTip();

while (true) {
const currentTip = await devnet.getTip();
if (currentTip.height >= initialTip.height + confirmations) {
break;
}
await new Promise(r => setTimeout(r, 100));
}
}

Troubleshooting

Blocks Not Producing

# Check node status
docker-compose -f devnet/docker-compose.yml logs cardano-node

# Restart with fresh state
npx cardano-devkit reset
npx cardano-devkit start --block-time 200

High CPU Usage

# Increase block time
npx cardano-devkit start --block-time 500

# Or reduce parallelism in tests

Timing Issues in Tests

// Add small delays between dependent operations
await lucid.awaitTx(hash1);
await new Promise(r => setTimeout(r, 300)); // Buffer
const tx2 = await buildNextTx();

Next Steps