Graceful Job Shutdown
Stop jobs cleanly.
Graceful Job Shutdown is a free Go Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Stopping Jobs Cleanly
A scheduler that is killed mid-job can corrupt data or leave half-finished work. Graceful shutdown means: stop accepting new runs, let in-flight jobs finish (up to a deadline), then exit.
Listening for Signals
Catch OS signals like SIGINT (Ctrl+C) and SIGTERM (orchestrator stop) so you can shut down on purpose.
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
fmt.Println("shutting down")signal.NotifyContext
Go 1.16+ offers a tidy helper that cancels a context when a signal arrives.
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
<-ctx.Done()Stopping the Scheduler
With robfig/cron, c.Stop() returns a context that is done once all running jobs complete. Wait on it to drain.
ctx := c.Stop() // stops scheduling, returns ctx
<-ctx.Done() // wait for running jobs
fmt.Println("all jobs finished")Propagating Cancellation to Jobs
Pass a context into each job so long-running work can abort promptly when shutdown begins.
func job(ctx context.Context) {
select {
case <-time.After(time.Hour):
case <-ctx.Done():
return // bail out early
}
}Bounding the Wait
Do not wait forever for stuck jobs. Use a timeout context so shutdown completes even if a job hangs.
shutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()WaitGroups for Custom Schedulers
If you roll your own with goroutines, track them with a sync.WaitGroup and Wait() during shutdown.
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); doWork() }()
// shutdown:
wg.Wait()Avoid Starting New Work
Once shutdown begins, the ticker/cron must stop firing. Closing a done channel or canceling the context ensures the loop sees the signal and stops scheduling new runs.
Idempotency Helps
Design jobs to be safe to re-run. If a job is killed mid-way and retried after restart, idempotent logic avoids duplicate effects (double emails, double charges).
The Full Pattern
Putting it together: a notify-on-signal context, a cron Stop that returns a drain context, and a bounded timeout. This is the standard graceful-shutdown skeleton for scheduled services.
Runnable: Graceful Stop With Context
This self-contained program runs a periodic worker and stops it gracefully via context cancellation, waiting for the in-flight tick to finish.
package main
import (
"context"
"fmt"
"sync"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
t := time.NewTicker(5 * time.Millisecond)
defer t.Stop()
for {
select {
case <-t.C:
fmt.Println("working")
case <-ctx.Done():
fmt.Println("stopping cleanly")
return
}
}
}()
time.Sleep(17 * time.Millisecond)
cancel() // signal shutdown
wg.Wait() // wait for worker to finish
fmt.Println("shutdown complete")
}Quick Check
Test your understanding of graceful job shutdown.
Recap
You learned graceful job shutdown:
- Catch SIGINT/SIGTERM, ideally via
signal.NotifyContext cron.Stop()returns a context that drains running jobs- Propagate context into jobs and bound the wait with a timeout
- Make jobs idempotent so retries are safe
Frequently asked questions
Is the “Graceful Job Shutdown” lesson free?
Yes — the full text of “Graceful Job Shutdown” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.
What will I learn in “Graceful Job Shutdown”?
Stop jobs cleanly. You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Go Academy?
No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Graceful Job Shutdown” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Go Academy lesson?
Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Time-Based Scheduling
- The robfig/cron Library
- Tickers for Intervals
- Graceful Job Shutdown