Firefly v1.0.4
Release date: August 4, 2026
v1.0.4 focuses on performance and correctness when large task sets become due at the same instant. The Scheduler JDBC path now uses bounded atomic batches instead of one transaction per task. On local PostgreSQL 16.14, the clear time for 50,000 same-due-time tasks fell from 477.068s to 3.572s.
Artifact publication status
The v1.0.4 source tag and Maven Central artifacts have not been published yet. Before upgrading production dependencies, confirm that 1.0.4 is indexed in Central Portal.
Test boundary
The stress suite covers JDBC Store, Scheduler, transactional Execution/Outbox writes, concurrent claims, and completion acknowledgement. It does not include CPU, network, or third-party latency from real business handlers.
Core changes
- Added a batch scheduling repository boundary, with bounded transactions of 200 tasks by default.
- Cursor CAS, execution inserts, and outbox inserts now use JDBC batches.
- Each batch borrows one connection, reads database time once, and commits once.
FORBIDconcurrency checks use one set query per batch instead of one query per task.- Shard ownership, fencing tokens, cursor CAS, and Execution/Outbox atomicity remain enforced.
- Added
firefly.scheduler.batch-size/FIREFLY_SCHEDULER_BATCH_SIZE, defaulting to 200.
Results
Tasks were registered in the future and armed to one shared due time only after registration completed, so scheduling metrics exclude registration time.
| Tasks | Before | Optimized | Optimized throughput | Speedup |
|---|---|---|---|---|
| 5,000 | 41.399 s | 0.906 s | 5,518.76/s | 45.7x |
| 10,000 | 101.295 s | 0.937 s | 10,672.36/s | 108.1x |
| 20,000 | 214.172 s | 1.869 s | 10,700.91/s | 114.6x |
| 50,000 | 477.068 s | 3.572 s | 13,997.76/s | 133.6x |
Scheduling delay
| Tasks | p50 | p95 | p99 | max |
|---|---|---|---|---|
| 5,000 | 199 ms | 210 ms | 213 ms | 214 ms |
| 10,000 | 204 ms | 213 ms | 216 ms | 216 ms |
| 20,000 | 427 ms | 454 ms | 456 ms | 458 ms |
| 50,000 | 886 ms | 927 ms | 932 ms | 936 ms |
Integrity
The 50,000-task run finished with:
firefly_job=50,000SUCCEEDED=50,000DONE=50,000- zero duplicate claims, execution IDs, or outbox IDs
- zero stale cursors or non-terminal outbox records
The 5,000-task contention topology also passed. Eight Scheduler instances competing for all tasks cleared the backlog in 1.769s without loss or duplication, validating CAS and fencing behavior under conflict.
Resource observations
| 50K metric | Observed value |
|---|---|
| JVM peak heap | 731.4 MiB |
| Java Working Set snapshot | 928.1 MiB |
| Java Private snapshot | 1,220.8 MiB |
| PostgreSQL CPU snapshot | 501.86% |
| PostgreSQL memory snapshot | 690.8 MiB |
| Main PostgreSQL waits | WALWrite / WALSync |
PostgreSQL now uses more CPU to process batched WAL writes while Scheduler threads spend far less time blocked on per-task transactions. The 50K total duration was 242.239s: task registration took 191.358s, the Outbox completion simulation took 46.004s, and Scheduler processing is no longer the dominant phase.
Configuration
firefly.scheduler.batch-size=200
firefly.scheduler.max-due-records-per-tick=10000
firefly.scheduler.max-idle-wakeup=PT0.5SDo not increase the batch without bounds. Larger batches increase transaction duration, rollback cost, and lease-expiry exposure. Tune against WAL capacity, JDBC pool limits, and the scheduling-delay SLO.
Verification
- PostgreSQL stress runs passed at 100, 5K, 10K, 20K, and 50K tasks.
- Added partial-CAS,
FORBID, and full-batch rollback tests. - The complete
gradle testsuite passed across Scheduler, JDBC, Outbox, Server, Netty, and remote Executor flows.
The source repository's docs/stress-test-v1.0.4.md contains the complete procedure, commands, resource data, and raw JSON references.