The Autocomplete Gap for Private Terraform Modules

Many development teams rely on Infrastructure as Code (IaC) tools like Terraform to manage their cloud resources. A key part of an efficient IaC workflow is the Integrated Development Environment (IDE) providing autocompletion and diagnostics. This feature significantly speeds up development, reduces errors, and improves code quality. However, a critical gap exists for teams using private Terraform modules: IDEs, specifically through the language server protocol (LSP) implementation like terraform-ls, often fail to provide autocompletion for modules not published to the public Terraform Registry.

The core of the problem lies in how terraform-ls, the primary language server for Terraform, fetches module information. Current implementations predominantly query the public Terraform Registry (registry.terraform.io). When a module is hosted privately, whether in a Git repository, a private registry, or even a monorepo with relative paths, terraform-ls cannot automatically discover and index its contents. This means developers lose the benefit of context-aware suggestions, type checking, and parameter hints for their own internal, proprietary modules. The result is a slower, more error-prone development experience, forcing engineers to constantly refer to documentation or source code manually.

This issue became apparent when two platform teams, previously operating independently and then merged through an acquisition, discovered their divergent approaches to managing Terraform modules. One team favored a monorepo structure where all infrastructure code was tightly coupled and deployed together using relative paths. The other team adopted a more modular approach, versioning their Terraform modules and consuming them via Git sources. While the latter is generally considered a more scalable and maintainable practice, it exposed the autocomplete deficiency when private, versioned modules were in play.

Example of a Terraform module block referencing a Git source

Understanding the Technical Limitation

The terraform-ls project, developed by HashiCorp, aims to provide a rich IDE experience for Terraform users. It parses Terraform configuration files, understands resource types, data sources, variables, and outputs. When dealing with modules, terraform-ls typically looks for modules specified via the source argument in a module block. If the source points to the public Terraform Registry, the language server can download the module's metadata and provide completions.

However, when the source points to a private Git repository (e.g., a GitHub, GitLab, or Bitbucket URL), a private module registry, or is a relative path within the same repository, terraform-ls does not have a built-in mechanism to authenticate, download, and index these private modules. The language server simply doesn't know about the available inputs, outputs, or resource types defined within these private modules. This forces developers to manually navigate to the module's source code to understand its interface, a tedious process that defeats the purpose of having intelligent code assistance.

One potential workaround involves manually creating stub modules or using external tools to generate metadata. However, these solutions are often brittle, require significant manual effort, and do not offer real-time, integrated autocompletion. The ideal solution would involve terraform-ls supporting authentication mechanisms for private Git repositories or private registries, allowing it to pull module information dynamically.

The Unanswered Question: Why the Lack of Urgency?

What is surprising is the apparent lack of widespread community outcry or urgent development focus on this issue. For teams managing a significant number of private, versioned modules, the absence of IDE autocompletion represents a substantial productivity bottleneck. Engineers must context-switch frequently, consult documentation, or rely on memory, all of which increase the cognitive load and the probability of errors. This is not a niche problem; many organizations build internal libraries of Terraform modules for common infrastructure patterns like VPCs, Kubernetes clusters, or database setups.

The technical challenges are not insurmountable. Language servers can be extended to support authentication tokens for Git providers or custom registry protocols. The tooling ecosystem around Terraform has matured considerably, with projects like tflint and various VS Code extensions offering advanced linting and formatting. Yet, the core language server functionality for private module introspection seems to be lagging. Is the complexity of handling various authentication methods too high? Are teams simply accepting this limitation as a cost of using private modules? Or are most teams still operating under simpler monorepo structures where this issue is less pronounced?

Diagram illustrating the flow of Terraform module discovery in terraform-ls

Potential Solutions and Community Efforts

While terraform-ls itself may not natively support private module autocompletion, the community is exploring workarounds. Some developers suggest configuring terraform-ls to use a specific local path for modules, effectively creating a local mirror of private modules. This requires a separate process to keep the local mirror synchronized with the actual private module source, adding operational overhead.

Another approach involves contributing to the terraform-ls project itself. Enhancements could include support for environment variables containing Git credentials, SSH keys, or API tokens that terraform-ls could utilize when fetching modules from private repositories. Additionally, support for common private registry protocols could be integrated.

The lack of a seamless experience for private modules highlights a broader tension in IaC tooling: balancing the benefits of public, standardized modules with the necessity of custom, private modules for enterprise-specific needs. As organizations increasingly adopt IaC for complex infrastructures, ensuring that developer tooling keeps pace with these evolving practices is crucial. Without robust IDE support for private modules, the promise of a frictionless IaC development workflow remains incomplete for a significant segment of the developer population.

Conclusion: A Call for Better Tooling

The absence of IDE autocompletion for private Terraform modules, primarily due to limitations in terraform-ls, is a persistent productivity drain. While workarounds exist, they often introduce complexity and manual effort. The community needs a more integrated solution that allows developers to leverage the full power of their IDEs when working with internal Terraform modules. This is not just a convenience feature; it's a fundamental aspect of efficient and error-free infrastructure development. If your team has found a robust solution or if you believe this issue warrants more attention, sharing your experience is vital to drive progress in this area.