Back to Articles

Nullstone: Building Heroku on Your Own Cloud With Terraform Guardrails

[ View on GitHub ]

Nullstone: Building Heroku on Your Own Cloud With Terraform Guardrails

Hook

What if you could give developers the simplicity of git push heroku main while your infrastructure team maintains full control over Terraform modules, compliance policies, and cloud spending—all without building an internal developer platform from scratch?

Context

The platform engineering dilemma has tormented engineering organizations for years: developers want Heroku's simplicity, but companies need the control, cost optimization, and compliance that comes from owning their cloud infrastructure. Kubernetes promised to solve this, but created new problems—YAML complexity, operational overhead, and a steep learning curve that pushed infrastructure concerns back onto application teams.

Terraform emerged as the infrastructure-as-code standard, but it presents its own challenge. While platform teams love the declarative approach and reusable modules, asking application developers to write HCL just to spin up a database is friction that slows shipping velocity. Companies either force developers to learn Terraform (creating bottlenecks), or build elaborate internal platforms (requiring dedicated teams to maintain). Nullstone enters this gap as a pre-built developer platform that uses your Terraform modules as building blocks, deployed directly into your cloud accounts through a CLI that abstracts the complexity.

Technical Insight

Nullstone's architecture revolves around a three-layer model: modules (Terraform configurations), blocks (instantiated infrastructure), and environments (deployment targets). The CLI communicates with a centralized Nullstone API that orchestrates Terraform execution in isolated workspaces, tracking state and dependencies.

Under the hood, Nullstone wraps Terraform workspace management with guardrails and conventions. When a developer runs nullstone up, the CLI doesn't execute Terraform locally—it sends instructions to the Nullstone service, which provisions the infrastructure using your team's approved modules. This centralization enables features like drift detection, dependency graphing, and audit logging without requiring developers to understand Terraform internals.

Here's what a typical workflow looks like from a developer's perspective:

# Authenticate with your Nullstone organization
nullstone set-context --org=acme-corp

# Create a new application block using a pre-approved module
nullstone create app my-api --stack=acme-corp/aws-fargate

# Configure environment variables
nullstone env set --app=my-api --env=production \
  DATABASE_URL="postgres://..." \
  REDIS_URL="redis://..."

# Deploy your application
nullstone launch --app=my-api --env=production --source=.

# View application logs
nullstone logs --app=my-api --env=production --follow

Behind this simple interface, Nullstone is executing Terraform plans, managing state files in S3 (or equivalent cloud storage), and tracking dependency relationships. The platform engineer who created the aws-fargate stack module wrote standard Terraform with some Nullstone-specific conventions in the module structure.

The module architecture uses Nullstone's contract system to define inputs and outputs. A simplified Fargate application module might declare capabilities like this:

# .nullstone/capabilities.json
{
  "capabilities": [
    {
      "name": "subdomain",
      "type": "public-subdomain"
    },
    {
      "name": "postgres",
      "type": "postgres/aws",
      "optional": true
    }
  ]
}

This contract tells Nullstone what dependencies the application needs. When a developer connects a Postgres datastore block to their application, Nullstone automatically injects connection credentials as environment variables—the developer never touches Terraform code.

The CLI itself is written in Go and organized around a plugin-style command structure using the Cobra library. Commands are grouped by resource type (apps, datastores, domains) and lifecycle operations (create, update, destroy). The source reveals extensive use of API client patterns, with each command ultimately making REST calls to the Nullstone service that performs the actual Terraform execution.

One architectural decision worth noting: Nullstone deploys infrastructure directly into your AWS/GCP/Azure accounts using credentials you provide, not into Nullstone-owned infrastructure. Your EC2 instances, RDS databases, and storage buckets live in your cloud account with your billing, security groups, and IAM policies. Nullstone merely orchestrates their creation—it's the control plane, not the data plane. This distinction matters for compliance, vendor lock-in concerns, and cost management.

Gotcha

The most significant limitation is that this CLI is only half the equation—you need access to Nullstone's commercial SaaS API service for the actual infrastructure orchestration. The repository itself is open source, but you can't run a fully self-hosted Nullstone platform using only this code. This creates a dependency on Nullstone-the-company for your infrastructure provisioning workflow, which may concern teams that prioritize operational independence.

The module ecosystem is another constraint. With only 43 GitHub stars, the community is nascent compared to the massive Terraform Registry or Pulumi ecosystem. You'll likely need to write custom modules for your specific infrastructure patterns, which means you still need Terraform expertise on your platform team. Nullstone reduces how many people need to know Terraform, but doesn't eliminate the requirement entirely. Documentation for building custom modules exists primarily on Nullstone's external documentation site rather than in the repository, making evaluation challenging without committing to the platform.

Verdict

Use if: You have a platform engineering team that wants to build internal developer platforms using Terraform modules as the foundation, but you don't want to build the orchestration layer, web UI, and CLI tooling from scratch. Nullstone gives you 80% of an internal platform with 20% of the effort. It's particularly compelling if you're already invested in Terraform, need multi-cloud support, and want developers deploying applications without learning IaC. The commercial SaaS model makes sense if you value maintained software over DIY control. Skip if: You need a fully open-source, self-hosted solution without external dependencies, or if you're comfortable with direct Terraform/Terragrunt workflows and don't see enough friction to justify another abstraction layer. Also skip if you're already deep in the Kubernetes ecosystem—tools like Crossplane or Argo CD might integrate more naturally. Teams with strong "not invented here" culture or strict requirements about external service dependencies should look at alternatives like building on Terraform Cloud's API or adopting Backstage with the Terraform plugin.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/nullstone-io-nullstone.svg)](https://starlog.is/api/badge-click/developer-tools/nullstone-io-nullstone)