aws-node-termination-handler: IMDS or Queue Processor, and why the choice is irreversible
Gracefully handle EC2 instance shutdown within Kubernetes
At a glance
- What is it?
- NTH cordons and drains Kubernetes nodes before EC2 takes them away, and it does so through one of two very different mechanisms: a per-host DaemonSet reading instance metadata, or a cluster Deployment consuming SQS messages. The choice between them decides what infrastructure you have to own.
- Who is it for?
- Choose the Queue Processor if you run ASG lifecycle hooks, because only that mode can hold the instance in a waiting state while the node drains, and accept the SQS plus EventBridge setup and IAM permissions that come with it. Choose IMDS if you want no AWS-side infrastructure at all and can accept that lifecycle hooks are unavailable.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- aws/aws-node-termination-handler1,763 ★ · +0
| Repository | 2026-10-16 | 2026-11-07 |
|---|---|---|
| aws/aws-node-termination-handler | 1.8k | 1.8k |
0 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
What NTH is protecting you from
The problem is narrow and worth stating precisely. Something outside your cluster decides that an EC2 instance is going away, and the Kubernetes control plane does not necessarily know in time to move work. The events that trigger this are EC2 maintenance events, Spot interruptions, ASG scale-in, ASG Availability Zone rebalance, and termination initiated through the API or console.
Left alone, the consequences are ordinary and bad. Application code does not stop gracefully, recovery to full availability takes longer, and pods may be scheduled onto a node that is already on its way out. NTH's response is the standard Kubernetes one: cordon the node so nothing new lands on it, then drain it so existing work leaves.
What makes this a project at all is that the notice has to arrive from AWS, through one of two paths, and the two paths have different latencies, different coverage and different operational costs. The whole design tension in this repository lives in that fork.
IMDS mode polls instance metadata
The Instance Metadata Service monitor runs a small pod on every host and watches metadata paths on the instance it runs on. The deployment shape is a DaemonSet, which is forced: one pod per node, each responsible for its own node. The paths it polls include `/spot` and `/events`, which correspond to Spot Instance Termination Notifications, Scheduled Events, Instance Rebalance Recommendations and Autoscaling Group Target Lifecycle State changes.
The advantage is that there is nothing to build on the AWS side. No queue, no rules, no permissions beyond what the instance already has to talk to its own metadata service. The cost is coverage. IMDS does not support lifecycle hooks, and the README is explicit about it. What it does support is lifecycle state change: when ASG uses the target lifecycle state, it writes `Terminated` into instance metadata before terminating, and NTH watches `latest/meta-data/autoscaling/target-lifecycle-state` and cordons and drains when it sees that value.
So in IMDS mode the instance is not being held in place while it drains. AWS is going to terminate on its own schedule, and NTH is racing it.
Queue Processor mode holds the instance still while the node drains
The Queue Processor takes a different route. EventBridge delivers ASG lifecycle events, EC2 status change events, Spot Interruption Termination Notice events and Spot Rebalance Recommendation events into an SQS queue, and NTH reads from that queue. The deployment shape is a Deployment, and it requires additional infrastructure: the SQS queue and the EventBridge rules, plus IAM permissions to monitor and manage the queue and to query the EC2 API.
The payoff is the mechanism the README describes for ASG lifecycle hooks. When a hook is configured, ASG sends the lifecycle action notification and then waits, either until the action is completed or until it times out. That waiting period is the window in which NTH receives the notification through SQS, cordons the node, drains it, and only then completes the lifecycle action. Only after the completion does ASG instruct EC2 to terminate.
That is the substantive difference between the modes. Lifecycle hooks convert termination from a deadline into a sequence. Scheduled events also arrive through this path, via AWS Health, and instance state change events cover the case where someone terminates an instance from the EC2 console or API rather than through the autoscaling group.
Picking a mode, and the coverage each one leaves behind
Coverage differences are the substance of the choice. Both modes monitor for events affecting your instances and both support Helm installation with event configuration, a webhook that can send shutdown or restart notification messages, and unit and integration tests. Beyond that the lists diverge.
The Queue Processor list is longer in a specific way: it adds ASG Termination Lifecycle Hooks, which in turn cover ASG scale-in, Availability Zone Rebalance and Unhealthy Instances, and it adds Instance State Change events. IMDS has Scheduled Events too, so the real gaps are hooks and state change events. In practice, configured ASG lifecycle hooks can hold a node for a drain, while a manual console termination cannot, in either mode, be extended.
Deployment type follows directly from mode. A DaemonSet for IMDS, a Deployment for the Queue Processor, and the Queue Processor being a single or small set of pods rather than one per node is what makes the SQS fan-in efficient.
If you use EKS managed node groups, the README says plainly that you do not need this project, since the managed group already handles node lifecycle for you. That removes NTH from the decision for those users.
Building it: the Makefile, the chart and the container image
The repository builds with Go. `go.mod` declares `go 1.25` with `toolchain go1.25.8`, and the Kubernetes client libraries are pinned at v0.30.4. The Makefile derives the version from `git describe --tags --always --dirty` and exposes the image name and chart name as overridable variables, with the image defaulting to `amazon/aws-node-termination-handler` and the public ECR path defaulting to `public.ecr.aws/aws-ec2/aws-node-termination-handler`. The supported Linux platforms are listed as `linux/amd64,linux/arm64`, and there is a `Dockerfile.windows` alongside the Linux one.
The Dockerfile shows the shape of the runtime image. It builds on `golang:1.25`, copies `go.mod` and `go.sum`, runs `go mod download`, then `make build`, and the final stage is `FROM scratch` with only the binary, the CA bundle copied in from `amazonlinux:2`, and `THIRD_PARTY_LICENSES.md`. It runs as user 1000, which is a small detail worth noticing in a network-facing daemon.
The Helm chart lives at `config/helm/aws-node-termination-handler`, which the Makefile reads to derive the chart version from `Chart.yaml`. The README states that both modes support Helm installation and event configuration but does not print a `helm install` command, so take the chart path and the image reference from the repository rather than from a blog post. For Windows, the Makefile notes that each Windows build needs its own target and runner, and pins the container base to `windows-10.0.20348.2582/amd64` for Windows Server 2022.
Limits, deprecations and what the build tells you
Two concrete constraints show up in the repository itself. Windows Server 2019 support has been removed, because GitHub Actions no longer supports that version, and the README instructs users to migrate to Windows Server 2022. That is a build infrastructure decision leaking into your cluster, which is the sort of coupling worth knowing about before you deploy on Windows nodes.
The Makefile also reveals a compatibility nuance. It defines a constant `K8S_1_32_ASSET_SUFFIX = "_k8s-1-32-or-newer"`, which suggests release assets are published in variants for clusters at 1.32 or newer versus older ones. The README badge states Kubernetes 1.23 or newer as the requirement. If you are near that boundary, check which asset you download rather than assuming the latest tag is universal.
Maintenance is a separate question from the feature set. The last push was on 2026-07-21 and the most recent release was v1.25.6 on 2026-04-02, after v1.25.5 on 2026-03-05 and v1.25.4 on 2026-01-27. The Apache-2.0 licence covers the project code, and `THIRD_PARTY_LICENSES.md` is carried into the image so the dependency licences travel with the binary, which is the arrangement you want from a component running with cluster-wide permissions.
Editorial conclusion
Choose the Queue Processor if you run ASG lifecycle hooks, because only that mode can hold the instance in a waiting state while the node drains, and accept the SQS plus EventBridge setup and IAM permissions that come with it. Choose IMDS if you want no AWS-side infrastructure at all and can accept that lifecycle hooks are unavailable. Before deploying either, check that you are not on EKS managed node groups, where the README states this project is unnecessary.
Frequently asked questions
What is the difference between IMDS mode and Queue Processor mode in aws-node-termination-handler?
IMDS runs a DaemonSet pod on each host that polls instance metadata paths such as `/spot` and `/events`, with no AWS-side infrastructure. The Queue Processor runs as a Deployment and consumes an SQS queue fed by EventBridge, which adds infrastructure and IAM permissions but also adds ASG lifecycle hooks and instance state change events.
Do I need aws-node-termination-handler on EKS managed node groups?
No. The README states that if you use EKS managed node groups you do not need the handler. It is aimed at self-managed clusters and other Kubernetes clusters running on AWS.
Does IMDS mode support ASG lifecycle hooks?
No, the README states IMDS does not support lifecycle hooks, only lifecycle state changes. With the target lifecycle state, ASG writes `Terminated` into instance metadata and NTH watches `latest/meta-data/autoscaling/target-lifecycle-state` to cordon and drain.
How does the Queue Processor drain a node before an ASG scale-in?
With lifecycle hooks configured, ASG sends the lifecycle action notification and waits. NTH receives it through SQS, cordons and drains the node, then completes the lifecycle action, and only then does ASG instruct EC2 to terminate the instance.
What does the Queue Processor need in terms of AWS permissions and infrastructure?
It requires an SQS queue and EventBridge rules, plus IAM permissions to monitor and manage the queue and to query the EC2 API. The IMDS mode needs neither.
Is Windows Server 2019 still supported?
No. Windows Server 2019 support has been removed because GitHub Actions no longer supports that version, and the README instructs users to migrate to Windows Server 2022.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/aws-aws-node-termination-handler)Star history chart for your README
[](https://hysenlabs.com/projects/aws-aws-node-termination-handler)Was this useful?