---
title: "Atlas Terraform Provider v0.4.0: HashiCorp partnerships, versioned migrations and more"
authors: giautm
tags: [terraform, versioned-migrations, release]
---
## Introduction

Today we are very excited to announce the release of Atlas Terraform Provider v0.4.0.
This release brings some exciting new features and improvements to the provider which
we will describe in this post.

In addition, this release is the first to be published under our new partnership with
[HashiCorp](https://hashicorp.com) as a [Technology Partner](https://www.hashicorp.com/partners/become-a-partner).
Atlas is sometimes described as a "Terraform for Databases", so we have high hopes that
this partnership will help us to bring many opportunities to create
better ways for integrating database schema management into IaC workflows.

![](https://atlasgo.io/uploads/images/hashicorp-partners.png)

## What's new

When people first hear about integrating schema management into declarative workflows,
many raise the concern that because making changes to the database is a high-risk operation,
they would not trust a tool to do it automatically.

This is a valid concern, and this release contains three new features that we believe will
help to address it:
* SQL plan printing
* Versioned migrations support
* Migration safety verification

## SQL Plan Printing

In previous versions of the provider, we displayed the plan
as a textual diff showing which resources are added, removed or modified. With this version,
the provider will also print the SQL statements that will be executed as part of the plan.

For example, suppose we have the following schema:

```hcl
schema "market" {
 charset = "utf8mb4"
 collate = "utf8mb4_0900_ai_ci"
 comment = "A schema comment"
}

table "users" {
 schema = schema.market
 column "id" {
   type = int
 }
 column "name" {
   type = varchar(255)
 }
 primary_key {
   columns = [
     column.id
   ]
 }
}
```

And our Terraform module looks like this:

```hcl
terraform {
 required_providers {
   atlas = {
     source  = "ariga/atlas"
     version = "0.4.0"
   }
 }
}

provider "atlas" {}

data "atlas_schema" "market" {
 src        = file("${path.module}/schema.hcl")
 dev_db_url = "mysql://root:pass@localhost:3307"
}

resource "atlas_schema" "market" {
 hcl        = data.atlas_schema.market.hcl
 url        = "mysql://root:pass@localhost:3306"
 dev_db_url = "mysql://root:pass@localhost:3307"
}
```

When we run `terraform plan` we will see the following output:

```text
Plan: 1 to add, 0 to change, 0 to destroy.
╷
│ Warning: Atlas Plan
│
│   with atlas_schema.market,
│   on main.tf line 17, in resource "atlas_schema" "market":
│   17: resource "atlas_schema" "market" {
│
│ The following SQL statements will be executed:
│
│
│ -- add new schema named "market"
│ CREATE DATABASE `market`
│ -- create "users" table
│ CREATE TABLE `market`.`users` (`id` int NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci
│
```

## Versioned migrations

Atlas supports two types of workflows: [Declarative and Versioned](/concepts/declarative-vs-versioned).
With declarative workflows, the plan to migrate the database is generated automatically
at runtime. Versioned migrations provide teams with a more controlled workflow where
changes are planned, checked-in to source control and reviewed ahead of time.
Until today, the Terraform provider only supported the declarative workflow. This release
adds support for versioned migrations as well.

Suppose we have the following migration directory of two files:

```sql title="20221101163823_create_users.sql"
CREATE TABLE `users` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `age` bigint(20) NOT NULL,
 `name` varchar(255) COLLATE utf8mb4_bin NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `age` (`age`)
);
```

```text title=atlas.sum
h1:OlaV3+7xXEWc1uG/Ed2zICttHaS6ydHZmzI7Hpf2Fss=
20221101163823_create_users.sql h1:mZirkpXBoLLm+M73EbHo07muxclifb70fhWQFfqxjD4=
```

We can use the Terraform Atlas provider to apply this migration directory to a database:

```hcl
terraform {
 required_providers {
   atlas = {
     source  = "ariga/atlas"
     version = "0.4.0"
   }
 }
}

provider "atlas" {}

// The `atlas_migration` data source loads the current state of the given database
// with regard to the migration directory.
data "atlas_migration" "hello" {
 dir = "migrations?format=atlas"
 url = "mysql://root:pass@localhost:3306/hello"
}

// The `atlas_migration` resource applies the migration directory to the database.
resource "atlas_migration" "hello" {
 dir     = "migrations?format=atlas"
 version = data.atlas_migration.hello.latest # Use latest to run all migrations
 url     = data.atlas_migration.hello.url
 dev_url = "mysql://root:pass@localhost:3307/test"
}
```

Running `terraform plan` will show the following output:

```text
data.atlas_migration.hello: Reading...
data.atlas_migration.hello: Read complete after 0s [id=migrations?format=atlas]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # atlas_migration.hello will be created
  + resource "atlas_migration" "hello" {
      + dev_url = (sensitive value)
      + dir     = "migrations?format=atlas"
      + id      = (known after apply)
      + status  = (known after apply)
      + url     = (sensitive value)
      + version = "20221101163823"
    }

Plan: 1 to add, 0 to change, 0 to destroy.
```


## Linting

Atlas provides extensive support for [linting](/versioned/lint) database schemas.
This release adds support for linting schemas as part of the Terraform plan. This means
that you can now run `terraform plan` and see if there are any linting errors in your
schema. This is especially useful when you are using the versioned migrations workflow, as you
can now run `terraform plan` to see if there are any linting errors in your schema
before you apply the changes.

Suppose we add the following migration:

```sql title="20221101165036_change_unique.sql"
ALTER TABLE users
 DROP KEY age,
 ADD CONSTRAINT NAME UNIQUE (`name`);
```

If we run `terraform plan` on the above schema, Terraform prints the following
warning:

```text
╷
│ Warning: data dependent changes detected
│
│   with atlas_migration.hello,
│   on main.tf line 20, in resource "atlas_migration" "hello":
│   20: resource "atlas_migration" "hello" {
│
│ File: 20221101165036_change_unique.sql
│
│ - MF101: Adding a unique index "NAME" on table "users" might fail in case column
│ "name" contains duplicate entries
╵
```

Atlas detected that the migration may fail in case the column `name` contains duplicate
entries! This is a very useful warning that can help you avoid unpredicted failed deployments.
Atlas supports many more safety checks, which you can read about [here](/lint/analyzers).

## Wrapping up

In this blogpost we have discussed three new features that were added to the Terraform Atlas provider
that are designed to make it safer and more predictable to manage your database schemas with Terraform.
We hope you will enjoy this release!

Have questions? Feedback? Feel free to reach out [on our Discord server](https://discord.gg/zZ6sWVg6NT).

