512 words
3 min read

Terraform contains() vs strcontains(): Which One, and the Gotchas

By · Docker Captain · CNCF Ambassador · IBM Champion
Cover image for the post 'Mastering Terraform Contains and Strcontains Functions'

Terraform is declarative. Which is a polite way of saying you don’t get if-statements like a normal programmer. You still need to validate inputs. You still need to gate deployments and steer behavior. So you reach for the logic tools the language actually hands you.

Two of them look trivial and turn out to be ridiculously useful: contains() and strcontains().

If a bad variable, a missing VM size, or a misnamed AZ has ever cost you a Saturday, read on.

Here’s how both work. No fluff.

contains(): is the value in there, or are you debugging all weekend#

contains() checks whether a specific value sits inside a list or a set.

contains(list, value) => bool

Returns true if the list has the value. false if it doesn’t. That’s the whole API.

Basic? Yes. But once your infra logic starts leaning on user input, region capabilities, or feature flags, this little function turns into the bouncer at the door of your Terraform nightclub.

Real example: Azure VM sizes#

Picture someone on the team requesting a beefy VM in a tiny region that can’t host it. You want to catch that before the apply blows up.

variable "region" {
default = "uksouth"
}
variable "vm_size" {
default = "Standard_DS2_v2"
}
data "azurerm_virtual_machine_sizes" "example" {
location = var.region
}
output "is_supported" {
value = contains(data.azurerm_virtual_machine_sizes.example.sizes, var.vm_size)
}

If vm_size isn’t offered in that region, you get false. Feed that into a count, a for_each, or a validation block. Whatever you pick, it beats watching Terraform barf mid-deploy.

strcontains(): when you’re parsing strings like it’s bash again#

Now strcontains(). This is Terraform answering one question: does this string have that other string inside it?

strcontains(string, substr) => bool

Reach for it when there’s no list, just a single string. An AZ name, a tag, a label. You want to match a pattern in it.

Example: is this AZ optimized#

strcontains("us-east-1b-optimal", "optimal") // returns true

It earns its keep when providers or modules hand back strings with metadata baked in and you need to route logic off that.

Say you only want to deploy when the target zone is labeled “optimal”:

locals {
is_optimal_zone = strcontains(var.availability_zone, "optimal")
}

Now local.is_optimal_zone is your switch. Use it to create resources, set tags, add taints, whatever the condition gates.

Gotchas that bit me, so they don’t bite you#

  • contains() wants the exact value. Case-sensitive. No fuzzy matching.
  • strcontains() doesn’t do regex or wildcards. Pure substring, nothing more.
  • Maps don’t behave with contains() the way you’d hope. Lists and sets only. Try contains({ key = "val" }, "key") and you’ll be disappointed.
  • Nulls can wreck your results. Validate your variables, or wrap them in coalesce() when it matters.

Bonus: validate with style#

Want to enforce rules on inputs? Drop these functions into validation blocks.

variable "az" {
type = string
default = "us-east-1b-optimal"
validation {
condition = strcontains(var.az, "optimal")
error_message = "Only 'optimal' AZs are allowed for this deployment."
}
}

Now Terraform fails early, with a message a human can read, instead of crashing halfway through the plan.

TL;DR#

  • Reach for contains() with lists or sets.
  • Reach for strcontains() for substring checks on a single string.
  • Pair them with validation, count, or for_each for logic that stays clean and safe inside your modules.
  • Don’t guess. Test.

Vladimir Mikhalev

Docker Captain  ·  CNCF Ambassador  ·  IBM Champion

The Verdict — production-tested analysis on YouTube.

The Verdict

Inconvenient truths about shipping in the AI era

Container security, platform engineering, and the agentic shift — tested in production, argued without the hype. The verdict reaches your inbox the moment there's one worth sending.

Related Posts

Same category
  1. 1
    EKS Validation on a Real AWS Account: Twenty Cents a Run, Seven Failures No Mock Saw
    DevOps & Cloud · Proving an EKS platform on a real AWS account cost twenty cents a run. Seven failed runs before it found what mocked Terraform tests and kind never could.
  2. 2
    A Partial Read Is Not a Smaller Fleet: A GitHub API Rate Limit and the Numbers That Lied for an Hour
    DevOps & Cloud · A partial read published as the whole. For an hour the profile said 24 restore scripts across 15 repositories, and the fleet had 73 across 48. Three guards now.
  3. 3
    Restore Drills on a Clean Machine — Measured RTO for 47 Stacks, 19 Seconds to 7 Minutes
    DevOps & Cloud · Restore drills that measure RTO on a machine that never ran the stack, 47 templates weekly. Every same-host restore passed. The first clean one answered 500.
  4. 4
    Mutation Testing for Infrastructure Code — 153 Planted Bugs, Four Tests That Could Not Fail
    DevOps & Cloud · Mutation testing for infrastructure code, done by hand across fifteen repositories. 153 planted bugs, and four green tests that could never have failed.

Random Posts

Random
  1. 1
    Install Windows Server 2019 Server Core
    SysAdmin & IT Pro · Step-by-step guide to install Windows Server 2019 Server Core. Learn how to set up a minimal, secure, and efficient Windows Server environment.
  2. 2
    Install OpenJDK on Ubuntu Server
    SysAdmin & IT Pro · Step-by-step guide to installing OpenJDK on Ubuntu Server. Learn how to configure Java, set JAVA_HOME, and verify your environment for Java development.
  3. 3
    Install Zabbix on Ubuntu Server
    DevOps & Cloud · Install Zabbix on Ubuntu Server 22.04 with Apache, MySQL, and SSL. Full step-by-step guide with Certbot, secure configs, and database setup.
  4. 4
    watsonx.governance Enforcement Tracking — Sampled Compliance and the Unevidenced Run
    AI & MLOps · EU AI Act Article 12 wants a per-event record. Enforcement Tracking evidences thresholds on a schedule. What that gap costs, and the join key that closes it.
Terraform contains() vs strcontains(): Which One, and the Gotchas
https://heyvaldemar.com/mastering-terraform-contains-and-strcontains-functions/
Author
Vladimir Mikhalev
Published
2024-05-25
Updated
2026-11-05
License
CC BY-NC-SA 4.0