---
id: external-schema
title: External Integrations
slug: /atlas-schema/external
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Atlas allows loading the desired state of the database schema from external programs or ORMs, regardless of the
programing language they are written in. Once the schema is loaded, it can be used by the various Atlas commands
such as `atlas schema` and `atlas migrate`.

## Loading an External Schema

In order to load an external schema, you need first to create an `atlas.hcl` [config file](projects.mdx), if you don't
already have one and declare a new data source of type [`external_schema`](projects.mdx#data-source-external_schema) that
can be used later as the desired state. Let's explain this with an example.

Given the following `atlas.hcl` file:

<Tabs>
<TabItem value="mysql" label="MySQL" default>

```hcl title="atlas.hcl"
data "external_schema" "orm" {
  # The first argument is the command to run,
  # and the rest are optional arguments.
  program = [
    "npm",
    "run",
    "generate-schema"
  ]
}

env "orm" {
  src = data.external_schema.orm.url
  dev = "docker://mysql/8/dev"
}
```

</TabItem>
<TabItem value="mariadb" label="MariaDB">

```hcl title="atlas.hcl"
data "external_schema" "orm" {
  # The first argument is the command to run,
  # and the rest are optional arguments.
  program = [
    "npm",
    "run",
    "generate-schema"
  ]
}

env "orm" {
  src = data.external_schema.orm.url
  dev = "docker:/maria/latest/dev"
}
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```hcl title="atlas.hcl"
data "external_schema" "orm" {
  # The first argument is the command to run,
  # and the rest are optional arguments.
  program = [
    "npm",
    "run",
    "generate-schema"
  ]
}

env "orm" {
  src = data.external_schema.orm.url
  dev = "docker://postgres/15/dev?search_path=public"
}
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```hcl title="atlas.hcl"
data "external_schema" "orm" {
  # The first argument is the command to run,
  # and the rest are optional arguments.
  program = [
    "npm",
    "run",
    "generate-schema"
  ]
}

env "orm" {
  src = data.external_schema.orm.url
  dev = "sqlite://dev?mode=memory"
}
```

</TabItem>
</Tabs>


Let's explain what is happening when running `atlas` with the `--env orm` command:

1. The `external_schema.orm` data source is loaded, by running the command `npm run generate-schema` and
   capturing its output as the desired state of the schema.
2. The program output should be defined as a list of SQL DDL statements separated by semicolon (`;`) or a
   [custom delimiter](../versioned/new.mdx#custom-statements-delimiter). More info about the format can be found in
   the [SQL schema page](sql.mdx#schema-definition). For example:
   ```sql {1,3}
   CREATE TABLE users (id int PRIMARY KEY, name text NOT NULL);

   CREATE TABLE posts (id int PRIMARY KEY, content text NOT NULL, author_id int NOT NULL REFERENCES users(id));
   ```
3. After the schema is loaded, Atlas utilizes the [dev-database](sql.mdx#dev-database) to parse and validate the
   SQL definition and converts them into its internal graph representation.
4. The loaded schema can be used by the various Atlas commands. For example:
   ```bash
   # Generating a new migration.
   atlas migrate diff --env orm
   # Applying the schema to the database.
   atlas schema apply --env orm
   ```

## Write an external loader

Most ORMs offer a way to generate a series of DDL statements from model definitions. For example, Java Hibernate enables
"schema exporting" using the `hbm2ddl` option, and Microsoft EF supplies a helper method called `GenerateCreateScript`
that lets users craft a small script to produce DDLs from their EF models. In a similar way, TypeORM users can use
the `createSchemaBuilder().log()` API, and so on.

A fully working implementation can be found in the [`atlas-provider-gorm`](https://github.com/ariga/atlas-provider-gorm)
repository, which is an external loader for the [GORM](https://gorm.io/) ORM.
