<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe" -->

---
title: Restarting a Go Program Without Downtime | daily.dev
description: A walkthrough of implementing zero-downtime restarts for Go services by duplicating listener sockets and passing them to a forked child process via signals...
canonical: https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Restarting a Go Program Without Downtime | daily.dev
og:description: A walkthrough of implementing zero-downtime restarts for Go services by duplicating listener sockets and passing them to a forked child process via signals...
og:url: https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe
og:image: https://api.daily.dev/og/posts/Q4bN0gLwe.png
og:image:alt: Restarting a Go Program Without Downtime
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Restarting a Go Program Without Downtime

**[Teleport](https://daily.dev/sources/teleport)** · 9 min read · 0 upvotes · 0 comments

## Summary

A walkthrough of implementing zero-downtime restarts for Go services by duplicating listener sockets and passing them to a forked child process via signals (SIGUSR2, SIGQUIT). Covers the tradeoffs between SO_REUSEPORT and socket duplication, explains how Teleport implements this for its SSH/TLS listeners, and provides a complete standalone Go source example demonstrating the fork, socket handoff, and graceful shutdown sequence.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://goteleport.com/blog/golang-ssh-bastion-graceful-restarts>

## Questions this post answers

### How can I restart a Go server without dropping connections or causing downtime?

Duplicate the listener socket and pass it as a file descriptor to a forked child process, then gracefully shut down the parent once traffic drains. The parent listens for a signal like SIGUSR2, calls os.StartProcess with the listener file included, and the child recreates the net.Listener from the passed file descriptor while the old process finishes existing connections before exiting.

_Explore daily.dev for practical Go patterns on building resilient, zero-downtime network services._

### What is the difference between SO_REUSEPORT and duplicating a socket for restarting a server process?

SO_REUSEPORT lets multiple processes bind the same port with separate accept queues, which can occasionally drop pending TCP connections, while duplicating a socket and passing it as a file descriptor to a child process uses a single shared accept queue feeding multiple processes, avoiding that connection-drop risk and following the traditional Unix fork/exec model.

_Developers weighing socket-sharing strategies can find deeper systems-design comparisons on daily.dev._

### Why doesn't Go's os/exec package pass arbitrary open file descriptors to a child process?

Go's os/exec package only passes stdin, stdout, and stderr to a child process by default, most likely for safety reasons, so passing additional file descriptors like a listener socket requires using the lower-level os package primitives (via os.StartProcess and os.ProcAttr.Files) instead of os/exec.

_daily.dev helps Go developers track low-level standard library details like this while building services._

## Similar posts on daily.dev

- [Blog: Graceful Shutdowns in Go](https://daily.dev/posts/blog-graceful-shutdowns-in-go-hidlppkrp) · Wawandco · 74 upvotes · 0 comments
- [Shedding old code with ecdysis: graceful restarts for Rust services at Cloudflare](https://daily.dev/posts/shedding-old-code-with-ecdysis-graceful-restarts-for-rust-services-at-cloudflare-tdby3tvs4) · Cloudflare · 12 upvotes · 0 comments
- [Concurrent Servers: Part 8](https://daily.dev/posts/concurrent-servers-part-8-zoovycv9x) · Eli Bendersky · 1 upvotes · 0 comments

---

Tags: [#golang](https://daily.dev/tags/golang), [#networking](https://daily.dev/tags/networking), [#sre](https://daily.dev/tags/sre)

[View this post on daily.dev](https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Restarting a Go Program Without Downtime","url":"https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe"},"datePublished":"2026-08-23T12:22:05.922Z","dateModified":"2026-08-23T12:44:29.877Z","description":"A walkthrough of implementing zero-downtime restarts for Go services by duplicating listener sockets and passing them to a forked child process via signals...","image":"https://media.daily.dev/image/upload/s--ZrL_HSsR--/f_auto/v1722860399/public/Placeholder%2006","thumbnailUrl":"https://media.daily.dev/image/upload/s--ZrL_HSsR--/f_auto/v1722860399/public/Placeholder%2006","isAccessibleForFree":true,"articleSection":"Teleport","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Teleport","logo":"https://media.daily.dev/image/upload/s--Dw-Bbw6O--/c_limit,w_256/f_auto,q_auto/v1787487494/logos/teleport?_a=BAMAMicg0","url":"https://daily.dev/sources/teleport"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"golang,networking,sre","timeRequired":"PT9M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Teleport","item":"https://daily.dev/sources/teleport"},{"@type":"ListItem","position":3,"name":"Restarting a Go Program Without Downtime"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/restarting-a-go-program-without-downtime-q4bn0glwe#faq","mainEntity":[{"@type":"Question","name":"How can I restart a Go server without dropping connections or causing downtime?","acceptedAnswer":{"@type":"Answer","text":"Duplicate the listener socket and pass it as a file descriptor to a forked child process, then gracefully shut down the parent once traffic drains. The parent listens for a signal like SIGUSR2, calls os.StartProcess with the listener file included, and the child recreates the net.Listener from the passed file descriptor while the old process finishes existing connections before exiting. Explore daily.dev for practical Go patterns on building resilient, zero-downtime network services."}},{"@type":"Question","name":"What is the difference between SO_REUSEPORT and duplicating a socket for restarting a server process?","acceptedAnswer":{"@type":"Answer","text":"SO_REUSEPORT lets multiple processes bind the same port with separate accept queues, which can occasionally drop pending TCP connections, while duplicating a socket and passing it as a file descriptor to a child process uses a single shared accept queue feeding multiple processes, avoiding that connection-drop risk and following the traditional Unix fork/exec model. Developers weighing socket-sharing strategies can find deeper systems-design comparisons on daily.dev."}},{"@type":"Question","name":"Why doesn't Go's os/exec package pass arbitrary open file descriptors to a child process?","acceptedAnswer":{"@type":"Answer","text":"Go's os/exec package only passes stdin, stdout, and stderr to a child process by default, most likely for safety reasons, so passing additional file descriptors like a listener socket requires using the lower-level os package primitives (via os.StartProcess and os.ProcAttr.Files) instead of os/exec. daily.dev helps Go developers track low-level standard library details like this while building services."}}]}
```

