Backend Development 10 min read

Hot Reloading Go Configuration Files Using System Signals

This tutorial explains how to implement hot‑reloading of Go configuration files by manually sending Unix signals, covering the creation of a signal‑listening goroutine, use of the signal.Notify API, selective handling with select, and a complete example that loads JSON config on SIGUSR1.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Hot Reloading Go Configuration Files Using System Signals

In many Go projects configuration files (JSON, XML, YAML, or plain text) store essential metadata, and a long‑running process such as a web server often needs to reload these files when they change. Two approaches are introduced: manually sending a system signal and using inotify to watch file changes.

Manual method – using system signals

The idea is to notify the running program that the configuration has been updated by sending a Unix signal (e.g., SIGUSR1 ). A dedicated goroutine receives the signal and triggers the reload logic.

import "os/signal"

signal.Notify(c chan<- os.Signal, sig ...os.Signal)

Typical steps:

Create a buffered channel to receive signals.

Start a goroutine that calls signal.Notify with the desired signal (usually SIGUSR1 ).

Inside the goroutine, use an infinite for loop with a select statement to block until a signal arrives.

When a signal is received, invoke a configuration‑loading function.

The select statement works like a switch but only for channel operations, ensuring the goroutine blocks until a signal is placed on the channel.

Example of the signal‑listening goroutine:

func main() {
    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGUSR1)
    go func() {
        for {
            select {
            case <-sig:
                // load configuration here
                _ = loadConfig("/tmp/env.json")
            }
        }
    }()
    // keep the program alive
    select {}
}

Configuration loading logic

The loadConfig function reads the JSON file, checks its modification time against a cached timestamp, unmarshals the content into a struct, and updates a global configuration variable under a read‑write mutex.

type configBean struct {
    Test string
}

type config struct {
    LastModify time.Time
    Data       configBean // configuration content
}

var Config *config

func loadConfig(path string) error {
    locker := new(sync.RWMutex)
    data, err := ioutil.ReadFile(path)
    if err != nil {
        return err
    }
    fileInfo, err := os.Stat(path)
    if err != nil {
        return err
    }
    if Config != nil && fileInfo.ModTime().Before(Config.LastModify) {
        return errors.New("no need update")
    }
    var bean configBean
    if err = json.Unmarshal(data, &bean); err != nil {
        return err
    }
    cfg := config{LastModify: fileInfo.ModTime(), Data: bean}
    locker.Lock()
    Config = &cfg
    locker.Unlock()
    return nil
}

The function deliberately locks only around the assignment to avoid unnecessary contention, assuming only one goroutine writes to the file. If multiple goroutines may write concurrently, the file I/O should also be protected.

Putting it all together

The final main function sets up the signal channel, starts the listening goroutine, and blocks the process so it can react to signals:

func main() {
    configPath := "/tmp/env.json"
    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGUSR1)
    go func(path string) {
        for {
            select {
            case <-sig:
                _ = loadConfig(path)
            }
        }
    }(configPath)
    // block forever (or until another termination signal)
    select {}
}

The article also provides a link to the full source code on GitHub and notes that the demo omits error handling and signal‑channel cleanup, which readers should implement themselves.

Future work will cover the second method—using inotify to automatically watch file changes and trigger reloads without manual signals.

configurationGohot reloadgoroutineSignal HandlingSystem Signals
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.