Fast Blocks
Cardano DevKit supports sub-second block times (100-200ms) for rapid development iteration.
Why Fast Blocks?
| Standard Testnet | Local Devnet (Fast) |
|---|---|
| 20 second blocks | 100ms blocks |
| 40 seconds to confirm | 200ms to confirm |
| 3 transactions = 1 minute | 3 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 |
|---|---|---|
| 100 | 0.1 | Maximum speed, single dev |
| 200 | 0.2 | Fast development |
| 500 | 0.5 | Team development |
| 1000 | 1.0 | Default, stable |
| 20000 | 20.0 | Testnet simulation |
Performance Considerations
CPU Usage
Fast blocks increase CPU usage:
| Block Time | Relative CPU |
|---|---|
| 1000ms | 1x (baseline) |
| 500ms | 2x |
| 200ms | 5x |
| 100ms | 10x |
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();