Changelog¶
Every module in this repository (kiln, pgstore, mysqlstore, mssqlstore, sqlitestore, kilnotel, redisbus) is
released together under the same version. The GitHub releases have the full notes.
v1.0.0-rc.1 (2026-10-09)¶
The release candidate for v1.0.0. The code is v0.9.0's and the API is final: unless running this candidate shows that the API has to change, v1.0.0 will be the same code, and from then on Compatibility applies.
Docs¶
- A documentation site at https://kiln.rafaelaugusto.dev, in English and Brazilian Portuguese, with a guide to writing a store and a table of what each store does differently.
Upgrading¶
- No schema or API changes from v0.9.0.
v0.9.0 (2026-10-09)¶
The last release planned to break the API before v1.0.
Breaking¶
Client.OpenBatchtakes a*Batch, asStartBatchdoes, in place of a description and meta. It inserts the batch's jobs, continuations and nested batches and leaves the batch open, and it can open a batch nested in another throughBatch.Parent. ReplaceOpenBatch(ctx, desc, meta)withOpenBatch(ctx, &kiln.Batch{Description: desc, Meta: meta}).
Added¶
kiln.ErrConflict, so a conflict fromSetRecurringcan be checked without importingdriver.
Docs¶
- Compatibility: what stays stable across v1, how the store interface grows, and the Go versions kiln needs.
- The package docs name
mssqlstore, and the README says thatpgstore.Newopens a pool of its own.
Upgrading¶
- No schema changes. The only code to change is a call to
OpenBatch.
v0.8.2 (2026-10-09)¶
Added¶
- kilnotel: a
kiln.jobs.failedgauge with the jobs that failed for good and wait for a requeue or a delete, the number to alert on.
Fixed¶
- mysqlstore: a
TxWriterinsert that named a parent job and reused the unique key of that parent's parent could deadlock withFinish(error 1213, seen once in about 1,400 transactions under heavy concurrency). Inserts andRequeuenow take unique keys before jobs, asFinishalready did. - mssqlstore: under heavy concurrency a
TxWriterinsert could still be picked as a deadlock victim (1205) beside aRequeue. It takes the same order as MySQL now, and unique keys are claimed with a seek instead of aMERGEthat scanned other transactions' keys.
Docs¶
- Operating: size a kind's retries to outlast the longest outage of what it calls, and alert on
kiln.jobs.failed. - The results of the 24 hour soak, and how to run it on a server.
Upgrading¶
- No schema changes. Update every kiln module to v0.8.2 together, as usual.
v0.8.1 (2026-10-03)¶
Fixed¶
- mysqlstore: an insert through a
TxWriterthat names a parent job no longer deadlocks with aRequeueof that parent. The insert locked its unique keys before its parents and the requeue locked them the other way round, so the application's transaction could fail with error 1213. Inserts now lock their parents first. mssqlstore takes the same order, which removes the plain case; under heavy concurrency SQL Server can still pick such a transaction as a deadlock victim (1205). - mysqlstore, mssqlstore: a child released while its parent finishes is checked against a fresh clock, so it is enqueued at once instead of waiting up to a second as scheduled.
- dashboard: changing pages no longer fades the content out and back in.
Docs¶
- Recurring jobs: the spec is evaluated in UTC unless
TZsays otherwise, and occurrences overlap unlessOverlap(false)is set. - Operating: how deploys interact with
ShutdownTimeoutandKillGrace, and why each service should have its own queues.
Upgrading¶
- No schema changes. Update every kiln module to v0.8.1 together, as usual.
v0.8.0 (2026-10-03)¶
Added¶
- Nested batches:
Batch.AddBatchnests a batch in another, which then finishes only after every batch nested in it, andBatch.Parentnests a new batch in one that is still open.driver.NewBatch,driver.BatchQueryanddriver.BatchgainParent;driver.BatchgainsNestedandNestedFinished. - The dashboard comes in English and Brazilian Portuguese, chosen from a picker in the header,
dashboard.Options.Languageor the browser's language. The catalogs live indashboard/locales. - The dashboard shows a batch's parent and the batches nested in it;
/api/batches?parent=IDlists them.
Fixed¶
- pgstore: a limit rule written after an admission retry no longer replaces a newer rule that another insert wrote in the meantime.
- mssqlstore: finishes running in parallel no longer leave each other's batches to the leader's sweep.
Changed¶
- The rate limit docs say that the bound holds over admission times. soak reports a rate window over the bound right after a database restart or stall as a warning.
Upgrading¶
- Additive schema change
006_nested_batches; v0.7 servers keep running next to v0.8 during a rolling deploy, but nest batches only once every server runs v0.8.
v0.7.0 (2026-10-03)¶
Added¶
- Job titles:
kiln.Titleor aTitle()method on the args names a job in the dashboard. - A tag filter on the dashboard's job lists, backed by
driver.JobQuery.Tag. Unique{Replace: true}updates a holder that hasn't started with the new args, andUnique{Debounce: d}runs the jobdafter the last enqueue.driver.InsertedgainsReplaced.Job.ParentOutputsreturns the outputs of a continuation's parents that succeeded.Pool.Weightsshares a pool's claims between its queues by weight instead of strict order.soak/, a chaos harness that kills workers and restarts the database while it checks that no job is lost.
Fixed¶
- drivertest's fan-in case gives parents waiting on a busy child 15s instead of 3s, enough for SQL Server on a small CI runner.
Upgrading¶
- Additive schema change
005_job_extras; v0.6 servers keep running next to v0.7 during a rolling deploy.
v0.6.0 (2026-10-02)¶
Added¶
- Job console:
Job.LogfandJob.SetProgresswrite log lines and a progress bar that the dashboard shows live on the job's page, grouped by attempt. Stores implement the optionaldriver.Console;kilntest.Resultcarries the lines and the progress. Client.SyncRecurringkeeps a group of recurring jobs in step with the code: it sets the ones it's given and removes the rest of the group.driver.RecurringgainsGroup.- A Limits page in the dashboard, and
GET /api/limits: per key, the rule and how many jobs are active, throttled and holding a reserved start. Stores implement the optionaldriver.LimitReader.
Upgrading¶
- Additive schema changes
003_consoleand004_recurring_group; v0.5 servers keep running next to v0.6 during a rolling deploy.
v0.5.0 (2026-10-02)¶
Added¶
mssqlstore: SQL Server 2019+ and Azure SQL, on any*sql.DBfromgo-mssqldb, with an optionaldriver.Busfor wakeups. It passes the same conformance suite as the other stores; the database needsREAD_COMMITTED_SNAPSHOT.
Changed¶
- The stores agree on a few edge cases, each pinned by a conformance case:
Seriesleaves out the bucket atto, aFinishoutcome whose State isn't one of the five is Rejected,Outputis kept only for succeeded and deleted jobs, and a limit of 0 or less counts as 1. - Jobs that a transactional writer's
SealBatchreleases are admitted byNotify, like inserted ones, instead of waiting for the sweep (pgstore, mysqlstore). Closecan be called more than once on every store.
Fixed¶
- sqlitestore reads SQLite's error codes from any driver, so an outcome SQLite refuses is Rejected with mattn and ncruces too.
- memstore's
Sweeprespects its limit, and itsTxkeeps aUniqueForwindow from the insert. - mysqlstore's
Delete,RequeueandPrunecount only work that committed.
v0.4.1 (2026-10-02)¶
Fixed¶
- mysqlstore: an insert no longer waits behind a limits row that another transaction holds. Only an insert that changes that key's rule does. A held row used to stall every insert in the process, with or without a limit.
- Delete and
Finishno longer deadlock over a limits row when a job is deleted while its parent finishes (pgstore and mysqlstore).
Documentation¶
- Doc comments on the store packages:
memstore,drivertest,pgstore,mysqlstoreandsqlitestore. sqlitestoreneeds SQLite 3.38 or later; it was documented as 3.35.
v0.4.0 (2026-10-02)¶
Added¶
kilnotelmodule: OpenTelemetry spans from the enqueue to the handler, job metrics, and server and queue gauges.driver.Busand theredisbusmodule, which carries wakeups over Redis Pub/Sub so MySQL and SQLite servers in other processes start new jobs within milliseconds instead of on their next poll.Job.RunAt, the time the job became due.driver.TxWriter, the interface of every store's transactional writer,Notifyincluded.pgstore.Store.SQLTxfor applications ondatabase/sqlwith pgx's stdlib driver.- Doc comments on the exported API of
kiln,driver,cron,dashboard,kilntest,kilnotelandredisbus.
Changed¶
- Requeueing a failed, succeeded or deleted job starts it over with all of its attempts, instead of giving it one more (#5).
- The first time a job is rescued from a dead server it goes straight back to its queue; only a job rescued
twice in a row waits for its backoff (#6).
driver.OrphangainsLastReason. - A lost claim is requeued without using up an attempt.
- Large counts on the dashboard overview are shortened (167.4k, 1.2M) so they fit their cards.
Fixed¶
- Rate-limited jobs no longer start together after admission stalls: a second GCRA state per key,
admit_tat, letsBurstof them start and gives the rest new slots (#1). On PostgreSQL, admission no longer waits on limits rows, which removes the deadlocks between admit statements andFinish. - Limited jobs enqueued through a
memstore.Txare admitted when it commits (#2). - A server no longer requeues a job as lost while the claim that took it is still on its way back, which could run the job twice (#4).
kilntestcopiesRunAt, andkilnotelno longer counts a bareErrSnoozedas a snooze.
Upgrading¶
- Additive schema change
002_admit_gate: a nullableadmit_tatcolumn on the limits table. v0.3 servers keep running next to this version during a rolling deploy.
v0.3.1 (2026-09-25)¶
- A server that gets no notifications from its store looks for due jobs every 100ms instead of every
PollInterval, so reserved rate-limit slots, delayed jobs and retries start on time on MySQL and on PostgreSQL without a workingLISTENconnection.
v0.3.0 (2026-09-24)¶
- Rate limits:
kiln.LimittakesRate,PerandBurstnext toMax. Start times are reserved when a job is admitted (GCRA), so a backlog is released at the configured pace and each job is written once. - Additive schema changes are recorded in a new
schema_changestable; v0.2 servers keep running during a rolling deploy. driver.InsertParamsgainsLimitRate,LimitPerandLimitBurst, and the conformance suite aRategroup.- READMEs for
pgstore,mysqlstoreandsqlitestore.
v0.2.0 (2026-09-24)¶
sqlitestore, for anydatabase/sqlSQLite driver.mysqlstorejoins the regular release.- Go 1.27 is the minimum version; pgx v5.11.0.
- The
compatmodule runs the previous release next to the new one on the same database. driver.CheckInsertanddriver.CheckFiltervalidate inputs the same way for every store.- Servers report the kiln version they run.
v0.1.0 (2026-09-24)¶
First public release: fire-and-forget, delayed and recurring jobs, continuations, flows and batches,
retries, snoozes and cancellation, unique jobs and concurrency limits, transactional enqueue, the
dashboard, pgstore, and the drivertest conformance suite.