It's May 2022, and MegaLinter has won. If you start a new repo today and need linting, you'll see MegaLinter on Stack Overflow, in dev blogs, and in every second pull-request template. One image, a hundred linters, one YAML, done. For 80 % of repos, that's exactly right.

This article is for the other 20 %. The ones where the MegaLinter image stretches your CI by four minutes. Where 95 of the bundled linters target tools you don't have. Where a generic fail message tells you "MegaLinter found problems" and you have to open the MegaLinter docs to find out which of the hundred linters is trying to say something.

The alternative: four clean layers, each with a clear responsibility, all individually pinnable.

Layer 4 — Domain Spectral · gherkin-lint · helm lint Layer 3 — Convention commitlint · semantic-release Layer 2 — Format markdownlint · Prettier · editorconfig Layer 1 — Language hadolint · tflint · ShellCheck · yamllint actionlint specific universal
Four layers from bottom (language linters, broadly applicable) to top (domain linters, domain-specific). Each layer individually pinnable, all running in parallel.

Layer 1 — Language Linters

Check syntactic correctness and language-specific best practices. The mandatory layer — nothing reaches main without it. Typical tools: hadolint for Dockerfiles, tflint for Terraform/OpenTofu, ShellCheck for Bash, yamllint for generic YAML, actionlint for GitHub-Actions workflows.

Each of these tools is small (Alpine images around 20-30 MB), fast (seconds), and has a clear job. Pin to specific versions — hadolint:2.10-alpine, not :latest — or a major upgrade will topple your pipeline.

Layer 2 — Format Linters

Check whether files are uniformly structured. The hygiene layer. Typical tools: markdownlint for Markdown, Prettier for JS/TS/CSS/JSON/YAML, editorconfig-checker for cross-language conventions.

Boundary to Layer 1: Layer 1 asks "is it correct?", Layer 2 asks "does it read consistently?". Format linters often have a --fix option — allow it locally in pre-commit, check only in CI.

Layer 3 — Convention Linters

Check git metadata — commits, branch names, release notes. The workflow layer. Most important tool: commitlint with @commitlint/config-conventional.

This layer runs before the others sequentially, because if the commit message is broken the rest doesn't matter. semantic-release and automated versioning are a house of cards without convention linting.

Layer 4 — Domain Linters

Check domain-specific structures — OpenAPI specs, feature files, Helm charts. The contract layer. Typical tools: Spectral for OpenAPI/AsyncAPI, gherkin-lint for BDD features, helm lint and kubeconform for Kubernetes manifests.

This layer only runs when relevant files have changed (path filters). Saves CI time, because not every commit touches domain files.

What that looks like in your pipeline

Three stages, four layer jobs:

  • Stage 1 — Convention. commitlint, sequential.
  • Stage 2 — Language + Format + Domain. Three jobs in parallel.

Total runtime after cache warm-up: typically 90-120 s. MegaLinter equivalent: 6-8 min. Four to five times faster, with clearer error output and individually pinnable tool versions.

What you can take away today

Three rules of thumb:

  • Pin every tool version. No :latest tags. A tool upgrade is a pull request.
  • Local = CI. What runs locally with just lint is exactly what runs in CI. Otherwise the pipeline becomes a feedback loop with a three-minute delay.
  • One layer per quarter. If your repo isn't yet layered, start with Layer 1. Adopting all four at once burns team patience.

If you want to go deeper

The short book "Linting in Layers — Four Layers Instead of One Mega-Linter" develops each layer over its own chapter with setup snippets per tool, CI and pre-commit configurations for GitHub Actions, GitLab CI, and Forgejo Actions, plus a worked-through example on a Postgres-operator repo. Three diagrams, a cheatsheet to pin on the wall. Around 80 pages, 90 minutes of reading. Published May 2022 as paperback and eBook via epubli.

About Jonas Veit

Jonas Veit has been working on build pipelines for over ten years, from classic Jenkins setups to modern container-native CI stacks. He has reduced linting setups to a deterministic minimum in several companies and writes about tooling choices that don't have to be rebuilt every two years. He lives in Hamburg.