diff --git a/.gitignore b/.gitignore
index 6f7cabca03b91fd95916e64836c1ac51eb207927..428d9e6d5f4d9be6dd871c77726010d7587d36d3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ pom.xml.asc
 .idea/
 /docs
 profiles.clj
+/metabase.db.*.db
diff --git a/src/metabase/db.clj b/src/metabase/db.clj
index ba5b3e06947c7e4336dae4b4d4307273f69cb49d..ba80e99261f1e0843e0c3c75aeb8bb94f9765685 100644
--- a/src/metabase/db.clj
+++ b/src/metabase/db.clj
@@ -1,5 +1,7 @@
 (ns metabase.db
-  (:require [clojure.tools.logging :as log]
+  "Korma database definition and helper functions for interacting with the database."
+  (:require [clojure.java.jdbc :as jdbc]
+            [clojure.tools.logging :as log]
             [clojure.string :as str]
             [environ.core :refer [env]]
             [korma.core :refer :all]
@@ -18,3 +20,21 @@
             (h2 {:db (get-db-file)
                  :naming {:keys str/lower-case
                           :fields str/upper-case}})))
+
+(defn migrate
+  "Migrate the database :up or :down."
+  [direction]
+  (let [conn (jdbc/get-connection {:subprotocol "h2"
+                                   :subname (get-db-file)})]
+    (case direction
+      :up (com.metabase.corvus.migrations.LiquibaseMigrations/setupDatabase conn)
+      :down (com.metabase.corvus.migrations.LiquibaseMigrations/teardownDatabase conn))))
+
+;;; UTILITY FUNCTIONS
+
+(defn ins
+  "Wrapper around `korma.core/insert` that renames the `:scope_identity()` keyword in output to `:id`
+   and automatically passes &rest KWARGS to `korma.core/values`."
+  [entity & kwargs]
+  (-> (insert entity (values (apply assoc {} kwargs)))
+      (clojure.set/rename-keys ({keyword "scope_identity()"} :id))))