# How do you do database migration/evolution?

**URL:** https://clojureverse.org/t/how-do-you-do-database-migration-evolution/2005
**Category:** Watercooler
**Tags:** clojure
**Created:** [April 20, 2018, 3:36pm UTC](https://clojureverse.org/t/how-do-you-do-database-migration-evolution/2005 "2018-04-20T15:36:37Z")
**Posts on this page:** 1
**Showing post:** 2

<div class="post-metadata">

### Author: ![pesterhazy](https://clojureverse.org/user_avatar/clojureverse.org/pesterhazy/32/395_2.png) [@pesterhazy](https://clojureverse.org/u/pesterhazy)
#### Post date: [April 20, 2018, 5:07pm UTC](https://clojureverse.org/t/how-do-you-do-database-migration-evolution/2005/2 "2018-04-20T17:07:50Z")

</div>

A minimalist approach is to store the migrations as .sql files in a folder, then run them via a command line client like `psql` or from your Clojure code via JDBC.

For Postgres, I’ve come up with a [minimalist framework](https://gist.github.com/pesterhazy/9f7c0a7a9edd002759779c1732e0ac43). It’s so simple that it doesn’t really deserve the name “framework”. In a nutshell the `idempotent` function ensures that a particular migration (say, CREATE TABLE) is run only once. Subsequent runs are NOOPs. Completed migrations are stored in the `migrations` table.

Advantages over “real” migration tools like [flyway](https://flywaydb.org/):

- it’s fast if there’s nothing to do so you can easily run all migrations whenever your JVM process starts
- you know exactly what’s going on
- it’s all just SQL so the sql snippets can include data migrations (`UPDATE foo ...`) as well as schema migrations (`ALTER TABLE foo ...`)

Limitations include lack of support for rolling back migrations. But if your use case is like mine, you may not need that functionality (and appreciate the fact that the code fits on a postcard).

---

_[View the full topic](https://clojureverse.org/t/how-do-you-do-database-migration-evolution/2005)._
