What Is TFLint?
TFLint is a linter for Terraform that catches errors terraform validate misses. It checks for:
- Invalid instance types (
t2.giganticdoesn’t exist) - Deprecated resource attributes
- Naming convention violations
- Provider-specific best practices (AWS, Azure, GCP)
- Missing required tags
terraform validate only checks syntax. TFLint checks whether your configuration makes sense.
Install TFLint
macOS (Homebrew)
brew install tflint
Linux
curl -s https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash
Windows (Chocolatey)
choco install tflint
Docker
docker run --rm -v $(pwd):/data -t ghcr.io/terraform-linters/tflint
Verify installation:
$ tflint --version
TFLint version 0.53.0
Quick Start
cd my-terraform-project/
tflint --init # Download plugins
tflint # Run linter
That’s it. TFLint scans all .tf files in the current directory.
Configure TFLint: .tflint.hcl
Create .tflint.hcl in your project root:
# .tflint.hcl
# Enable the AWS plugin
plugin "aws" {
enabled = true
version = "0.32.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
# Enforce naming conventions
rule "terraform_naming_convention" {
enabled = true
}
# Require descriptions on variables
rule "terraform_documented_variables" {
enabled = true
}
# Require descriptions on outputs
rule "terraform_documented_outputs" {
enabled = true
}
# Disallow deprecated syntax
rule "terraform_deprecated_interpolation" {
enabled = true
}
# Enforce standard module structure
rule "terraform_standard_module_structure" {
enabled = true
}
Then initialize:
$ tflint --init
Installing `aws` plugin...
Installed `aws` (source: github.com/terraform-linters/tflint-ruleset-aws, version: 0.32.0)
What TFLint Catches (That terraform validate Doesn’t)
Invalid Instance Types
resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "t2.superduper" # Doesn't exist!
}
$ tflint
1 issue(s) found:
Error: "t2.superduper" is an invalid value as instance_type (aws_instance_invalid_type)
on main.tf line 3:
3: instance_type = "t2.superduper"
terraform validate would pass this. terraform apply would fail after waiting for the API call.
Invalid AMI
resource "aws_instance" "web" {
ami = "not-an-ami"
}
TFLint catches the invalid AMI format before you waste time on a failed plan.
Deprecated Syntax
# Old interpolation-only syntax
resource "aws_instance" "web" {
instance_type = "${var.instance_type}" # Deprecated since Terraform 0.12
}
Warning: Interpolation-only expressions are deprecated (terraform_deprecated_interpolation)
Missing Tags
With the AWS plugin, you can enforce required tags:
# In .tflint.hcl
rule "aws_resource_missing_tags" {
enabled = true
tags = ["Environment", "Team", "ManagedBy"]
}
Now every AWS resource must have these tags or TFLint reports an error.
Provider Plugins
AWS Plugin
plugin "aws" {
enabled = true
version = "0.32.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
Checks: invalid instance types, invalid AMIs, invalid IAM policy actions, security group rules, and more.
Azure Plugin
plugin "azurerm" {
enabled = true
version = "0.27.0"
source = "github.com/terraform-linters/tflint-ruleset-azurerm"
}
Google Cloud Plugin
plugin "google" {
enabled = true
version = "0.30.0"
source = "github.com/terraform-linters/tflint-ruleset-google"
}
Built-In Terraform Rules
These rules work without any provider plugin:
| Rule | What It Checks |
|---|---|
terraform_naming_convention | Resource/variable/output naming patterns |
terraform_documented_variables | Variables have descriptions |
terraform_documented_outputs | Outputs have descriptions |
terraform_deprecated_interpolation | "${var.x}" → var.x |
terraform_unused_declarations | Unused variables, data sources, locals |
terraform_standard_module_structure | main.tf, variables.tf, outputs.tf exist |
terraform_workspace_remote | Warns about terraform.workspace with remote backends |
terraform_required_version | required_version is declared |
terraform_required_providers | required_providers block exists |
Enable them all for strict projects:
rule "terraform_naming_convention" { enabled = true }
rule "terraform_documented_variables" { enabled = true }
rule "terraform_documented_outputs" { enabled = true }
rule "terraform_deprecated_interpolation" { enabled = true }
rule "terraform_unused_declarations" { enabled = true }
rule "terraform_standard_module_structure" { enabled = true }
rule "terraform_required_version" { enabled = true }
rule "terraform_required_providers" { enabled = true }
CI/CD Integration
GitHub Actions
name: Terraform Lint
on: [pull_request]
jobs:
tflint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: terraform-linters/setup-tflint@v4
with:
tflint_version: v0.53.0
- run: tflint --init
- run: tflint --format compact
GitLab CI
tflint:
image: ghcr.io/terraform-linters/tflint:latest
script:
- tflint --init
- tflint --format compact
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
Pre-Commit Hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/terraform-linters/tflint
rev: v0.53.0
hooks:
- id: tflint
Output Formats
tflint # Default (human-readable)
tflint --format compact # One line per issue
tflint --format json # Machine-readable JSON
tflint --format junit # JUnit XML for CI
tflint --format sarif # SARIF for GitHub Code Scanning
TFLint vs Other Tools
| Tool | What It Does | When to Use |
|---|---|---|
terraform validate | Syntax check only | Always (fast, built-in) |
| TFLint | Syntax + provider-specific + best practices | Always (catches real errors) |
terraform plan | Full API check against real infrastructure | Before apply |
tfsec / trivy | Security scanning | Security audits |
checkov | Policy compliance | Compliance requirements |
terraform-docs | Generate documentation | Module documentation |
Recommended pipeline order: terraform fmt → tflint → terraform validate → terraform plan
Common Configuration Examples
Enforce snake_case naming:
rule "terraform_naming_convention" {
enabled = true
format = "snake_case"
}
Ignore specific rules for a module:
tflint --ignore-rule=terraform_documented_variables
Lint a specific directory:
tflint --chdir=modules/vpc/
Recursive lint (all modules):
tflint --recursive
Hands-On Courses
Learn by doing with interactive courses on CopyPasteLearn:
Conclusion
TFLint catches real errors that terraform validate misses — invalid instance types, missing tags, deprecated syntax, naming violations. Install it, add a .tflint.hcl with the AWS/Azure/GCP plugin, and integrate it into your CI pipeline. Run tflint before terraform plan to catch mistakes before they reach infrastructure.



