Skip to main content

SuspendApp with Ktor

There are some cases where it is convenient to gracefully shutdown a Ktor server. Basically, it is about giving some time to the server to finish some pending processing before turning it off.

Kubernetes is a good example of this need. When we're working with Kubernetes we often need to support Graceful Shutdown. Kubernetes sends SIGTERM to our Pod to signal it needs to gracefully shutdown. However, there is an issue which doesn't allow us to immediately shutdown when we receive SIGTERM from Kubernetes. Our pod can still receive traffic after SIGTERM, so we need to apply additional back-pressure to delay graceful shutdown.

Additional reading

More information on this can be found in this blog by Phil Pearl, and on learnk8s.io.

The module suspendapp-ktor provides a server constructor that lifts the Ktor ApplicationEngine in to a Resource, representing the Engine running an Application(i.e Netty) while supporting auto-reload. The example below introduces graceful shutdown for Kubernetes; we additionally use awaitCancellation to await SIGTERM, SIGINT or other shutdown hooks.

fun main() = SuspendApp {
resourceScope {
server(Netty) {
routing {
get("/ping") {
call.respond("pong")
}
}
}
awaitCancellation()
}
}

When the release function of our ApplicationEngine is called, there is a wait period before the beginning of the stop process (defaulted to 30.seconds), this gives Kubernetes enough time to do all its network management before we shut down. Two more parameters are available:

  • grace which sets the number of seconds during which already inflight requests are allowed to continue before the shutdown process begins,
  • timeout which sets the number of seconds after which the server will be forceably shutdown.
Development mode

In the case that Ktor server is set in development mode, the wait period is ignored.