DNS as Code in Action: Lessons from a Client Project with NS1 and Terraform

31 / Jan / 2026 by Karandeep Singh 0 comments

Introduction

DNS is rarely the first thing teams modernise. In most client environments we work with at To The New, CI/CD, cloud infrastructure, and observability mature quickly. DNS, however, often remains manually managed through dashboards, handled by a few people, and changed mostly during incidents. That gap usually goes unnoticed until traffic needs to be rerouted, a migration is planned, or an issue arises in production.

DNS As Code

DNS As Code

This blog shares how, in one of our ad-tech client projects, we transitioned DNS from manual operations to DNS as Code, utilizing NS1 (an IBM product) and Terraform, and what changes occurred afterward.

What We Found in the Client Setup

The client had a reasonably mature DevOps setup:

  • Infrastructure managed using Terraform
  • Clear deployment pipelines
  • Defined environments

But DNS changes were different. They were:

  • Made directly in the NS1 UI
  • Applied mostly in production
  • Not reviewed or documented
  • Hard to trace during incidents
  • DNS had effectively become a manual production dependency.

Why We Pushed for DNS as Code

At To The New, our default approach is simple:

  • If it affects production traffic, it should live in Git.
  • DNS is the very first layer users hit. Managing it outside version control increases operational risk, especially when traffic routing and failover logic are involved.
  • Since the client already used Terraform extensively, bringing DNS under the same workflow was a natural next step.

Why NS1 Fits This Approach

NS1 wasn’t just being used as a DNS provider; it was already part of the client’s traffic management strategy. What worked in our favour:

  • Support for weighted routing
  • Metadata-based decisions
  • Clear Terraform support
  • This allowed us to model DNS behavior declaratively, rather than treating it as a static configuration.

Terraform + NS1: The Core Model

In Terraform, you manage:

  • Zones
  • Records
  • Answers
  • Metadata
  • Routing behavior
  • Everything lives in Git.

Provider Configuration

provider "ns1" {
  api_key = var.ns1_api_key
}

This makes NS1 just another Terraform provider—no special treatment, no UI dependency. Managing DNS Records Declaratively.

Example: Simple A Record

resource "ns1_record" "application_1" {
  zone   = "demo.com"
  domain = "app1.demo.com"
  type   = "A"
  ttl    = 60
  answers {
    answer = ["10.53.1.98"]
  }
}

A DNS record is now:

  • Versioned
  • Reviewable
  • Reproducible

No surprises.

Sample Command used for importing existing records into Terraform:

terraform import ns1_record.<terraform_resource_name> <zone>/<domain>/<type>

Moving DNS into Terraform

We started small. Existing records were recreated in Terraform, without changing behavior. The goal was not optimisation, it was control and visibility. Once records lived in code:

  • Every change had a history
  • Reviews became mandatory
  • Ownership was clear
  • DNS stopped being something “handled on the side”.

GitOps in Practice for DNS

After this, DNS changes followed the same workflow as infrastructure changes:

  • Change proposed through a pull request
  • Terraform plan reviewed by the team
  • Merge triggered Terraform apply
  • NS1 updated records automatically
  • No direct NS1 dashboard access was required for day-to-day work.

This alone reduced risky, last-minute DNS changes significantly.

A Real Use Case: Gradual Traffic Migration

One practical scenario where this helped was a backend migration. Instead of switching traffic in one go, we used weighted DNS routing to:

  • Route a small percentage of traffic to the new backend
  • Observe behavior in real traffic
  • Gradually increase the load
  • Each weight change was a Git commit.
  • Each adjustment was reviewed.

There was no ambiguity about what changed or when. Environment Consistency Improved Immediately.

Before Terraform: DNS records for non-production environments were created manually and didn’t always match production logic.

With DNS as Code:

  • Same structure across all environments
  • Only the values differed
  • No accidental drift
  • Debugging environment-specific issues became much easier.
  • Rollbacks Stopped Being Stressful

Earlier, rolling back a DNS change meant:

  • Remembering the previous state
  • Manually updating records
  • Hoping nothing was missed

With Terraform:

  • Revert the commit
  • Apply the change
  • Done
  • DNS rollbacks became routine instead of risky.

Lessons from the Implementation

A few things we learnt during this project:

  • Keep TTLs low for records involved in routing decisions
  • Avoid making “quick fixes” directly in the UI
  • Start with simple routing logic and evolve gradually
  • Treat DNS changes like application changes
  • DNS doesn’t need to be complicated—but it does need discipline.

Closing Thoughts

DNS is often treated as background infrastructure. In reality, it’s a critical part of the request flow and availability. In this client engagement, bringing DNS into the GitOps model using NS1 and Terraform:

  • Reduced operational risk
  • Improved confidence during changes
  • Aligned DNS with the rest of the platform

At To The New, this approach has now become a standard recommendation for teams using intelligent DNS at scale. DNS may be old, but how we manage it should reflect modern engineering practices.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *