# Ecto: Query-Building Toolkit for Elixir and Databases

> Ecto separates data mapping from persistence, so you can validate and shape data against a schema before writing to PostgreSQL, MySQL, SQLite, or non-database sources. One toolkit works for databases or plain data structures.

**elixir-ecto/ecto** — A toolkit for data mapping and language integrated query.

- Repository: https://github.com/elixir-ecto/ecto
- Website: https://hexdocs.pm/ecto
- Stars: 6,498 · Forks: 1,485
- Language: Elixir
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/elixir-ecto-ecto

## Getting started with the Repo module and migrations

Add `:ecto` to your dependencies in mix.exs with version ~> 3.10. The README gives a complete example: configure ecto_repos with your Repo module, specify database credentials (database name, username, password, hostname, port), define your Repo module with `use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres`, and define schemas. The examples/ directory contains a working example (examples/friends/) that shows the complete setup from dependencies through queries. Run `mix ecto.create` to create the database, `mix ecto.migrate` to run migrations generated with `mix ecto.gen.migration`, and use Repo functions like Repo.insert(), Repo.update(), Repo.delete(), and Repo.all() for queries. The Repo is the interface to the database; all database operations go through it.

## Ecto separates schemas from databases

Ecto is a toolkit for data mapping and language-integrated query. The key word is separation: your data schema is a value in code, not embedded in the database. You define how a table maps to an Elixir struct, validate data against that schema, and then persist it. This separation means Ecto works whether your data lives in PostgreSQL, MySQL, SQLite, or not in a database at all. You can use Ecto to map data from any source into Elixir structs, whether backed by a database or not. Supported databases include PostgreSQL, MySQL, MSSQL, SQLite3, ClickHouse, and ETS (Erlang Term Storage). For each database, you add both Ecto and a database adapter to your dependencies. PostgreSQL requires ecto_sql and postgrex. MySQL requires ecto_sql and myxql. SQLite3 uses ecto_sqlite3. MSSQL uses ecto_sql and tds. ClickHouse uses ecto_ch. ETS (in-memory storage) uses etso. This adapter architecture lets you swap backends without changing schema or query code. The README shows the pattern of defining a Repo module using Ecto.Repo and specifying an adapter like Ecto.Adapters.Postgres.

## How schemas and changesets work

You start by defining an Ecto.Schema module for a table or data structure. The schema lists fields with types: strings, integers, floats, booleans, and others. When you insert or update data, you create a changeset, which wraps the data and tracks what changed. Changesets validate data against your schema before touching the database. You can add custom validations to a changeset, and Ecto collects all errors at once, then reports them together rather than stopping on the first failure. A changeset also tracks the difference between the original and the new values, so the framework can generate an efficient UPDATE query that changes only what you modified. This avoids unnecessary updates to unchanged columns. The schema example in the README shows how to declare fields: `field :city` defaults to type :string, `field :temp_lo, :integer` is an integer, and `field :prcp, :float, default: 0.0` is a float with a default value. Ecto manages the struct, validation, and persistence lifecycle automatically.

## Installing Ecto and PostgreSQL

Add ecto to your mix.exs file, following the dependency version documented in the README (~> 3.10). For PostgreSQL, also add ecto_sql and postgrex:

```elixir
defp deps do
  [
    {:ecto_sql, "~> 3.0"},
    {:postgrex, ">= 0.0.0"}
  ]
end
```

Then run `mix deps.get` to fetch dependencies. In config/config.exs, specify the database name, username, password, hostname, and port. Define a Repo module in your application code that tells Ecto which database adapter to use, like `use Ecto.Repo, otp_app: :my_app, adapter: Ecto.Adapters.Postgres`. Finally, define your schema as an Ecto.Schema with field declarations and you are ready to query. The README shows complete examples for configuration and schema definition.

For IPv6 databases, add socket_options: [:inet6] to your configuration:

```elixir
config :my_app, MyApp.Repo,
  hostname: "db12.dc0.comp.any",
  socket_options: [:inet6]
```

## Database adapters and non-SQL sources

The core Ecto library handles schemas and changesets. Database interaction lives in adapters. The main adapters are in ecto_sql, which covers PostgreSQL, MySQL, MSSQL, and other SQL databases via the ecto_sql package and database drivers like postgrex (PostgreSQL), myxql (MySQL/MariaDB), and tds (MSSQL). SQLite3 uses ecto_sqlite3. ClickHouse and ETS (in-memory term storage) also have Ecto adapters (ecto_ch and etso). Because Ecto separates schema from persistence, you can write adapters for non-database sources like HTTP APIs or file systems. This makes Ecto useful for applications that need to validate and transform data regardless of where it comes from. The adapter pattern allows different backends to plug in without changing application code that defines schemas or queries.

## Version support and stability

Ecto version 3.0 declared the API stable, and the project's focus shifted to bug fixes and incremental changes. Current supported versions are v3.12 and later for bug fixes. Versions v3.8 through v3.11 receive security patches only. v3.7 and earlier are unsupported. The framework has a clear upgrade path: if you are on v3.8 or later, you can upgrade to the latest version with confidence that the API will not change in breaking ways. The repository maintains a CHANGELOG.md documenting all changes. The documentation is extensive: a getting started guide at hexdocs.pm/ecto/getting-started.html, online documentation at hexdocs.pm/ecto, a mailing list at groups.google.com/forum/#!forum/elixir-ecto, and free resources like Programming Ecto by Darin Wilson and Eric Meadows-Jönsson, or The Little Ecto Cookbook from Dashbit. The repository includes examples in the examples/ directory and guides in the guides/ directory.

## Query building without SQL strings

Ecto builds queries as Elixir data structures, not SQL strings. This means you can compose and reuse queries programmatically. Because queries are data, not strings, you get compile-time checking and IDE autocompletion. The Ecto query API supports common SQL operations: filtering with where clauses, ordering, limiting results, grouping, joins, associations, and aggregations like count, sum, and average. Each part of a query is chainable: Repo.all(from u in User, where: u.active == true, select: u.name) chains the where and select operations. The online documentation at hexdocs.pm/ecto covers the complete query API with examples. For complex queries, you can write custom SQL and wrap it in a fragment, but Ecto's expression-based API covers most use cases without raw SQL.

## Testing and deployment concerns

Running tests with Ecto requires the database or a containerized test environment. The repository includes a test suite and instructions for running integration tests. You can run unit tests with `mix test`, which runs the unit test suite. Integration tests live in integration_test and require ecto_sql in a sibling directory and the ECTO_PATH environment variable set to your Ecto checkout: `cd ../ecto_sql && ECTO_PATH=../ecto mix test.all`. For containerized testing, the project uses earthly, which sets up PostgreSQL, MySQL, and MSSQL containers for integration tests. Run with `earthly -P +all` or `earthly -P -i` to debug interactively. Once inside a containerized shell, you can inspect databases with psql, mysql, and sqlcmd. This complexity is typical when testing code that depends on databases: you cannot mock a changeset the same way you mock an API. The development process is documented in CONTRIBUTING.md.

## Conclusion

Ecto is the right choice when you need to map data from any source into strongly-typed Elixir structures and validate against a schema before persisting. It suits applications using PostgreSQL, MySQL, SQLite, or other supported databases, as well as applications that work with non-database data sources. Start by adding Ecto and your database adapter to mix.exs, run mix deps.get, configure your Repo in config/config.exs with connection details, define your schema as an Ecto.Schema, and use changesets to validate and transform data. The getting started guide at hexdocs.pm provides complete examples. For complex multi-step transactions, use Ecto.Multi to group operations.

## FAQ

### What does ecto- mean?

Ecto is a prefix meaning outside or external. In biology, ectoderm is the outer layer of an embryo. The library name reflects that Ecto sits outside your application logic, handling data mapping at the boundary between your code and external data sources.

### What is Ecto in Elixir?

Ecto is a toolkit for data mapping and language-integrated query. It defines schemas for your data, validates changes via changesets, and builds type-safe queries to databases or other data sources.

### Can I use Ecto without a database?

Yes. Ecto separates schema and validation from persistence. You can use Ecto.Schema and changesets to map and validate data from any source into Elixir structs, whether or not a database is involved.

### Which databases does Ecto support?

Ecto supports PostgreSQL, MySQL, MSSQL, SQLite3, ClickHouse, and ETS via different adapters. PostgreSQL and MySQL use the ecto_sql adapter with database-specific drivers.

### What is the current stable version of Ecto?

Version 3.0 declared the API stable. The latest versions are 3.12 and later for bug fixes, with security patches for v3.8 through v3.11. Versions 3.7 and earlier are unsupported.

## Sources

- [elixir-ecto/ecto on GitHub](https://github.com/elixir-ecto/ecto)
- [License: Apache-2.0](https://github.com/elixir-ecto/ecto/blob/master/LICENSE)
- [Project website](https://hexdocs.pm/ecto)
- [README](https://github.com/elixir-ecto/ecto/blob/master/README.md)
- [Releases](https://github.com/elixir-ecto/ecto/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/elixir-ecto-ecto
