diff --git a/backend/app.py b/backend/app.py
index 242861b2e634df92473ba31e864fe96a503b80b5..ec18e9b6ebbf8f9fd90d8e82d73e5a7d2111a8c4 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -1,7 +1,7 @@
 from flask import Flask, jsonify
 from flask_cors import CORS
 from flask_jwt_extended import JWTManager
-from flask_migrate import Migrate
+import flask_migrate
 from jsonschema.exceptions import ValidationError
 from werkzeug.exceptions import BadRequest
 
@@ -35,6 +35,8 @@ from helpers import (
 import cluster_config
 from config import *
 import logging
+import migration_reset
+import sys
 
 # Configure logging.
 from logging.config import dictConfig
@@ -64,8 +66,20 @@ app.logger.setLevel(logging.INFO)
 app.logger.info("Starting dashboard backend.")
 
 cors = CORS(app)
-Migrate(app, db)
+
 db.init_app(app)
+with app.app_context():
+    # We have reset the alembic migration history at Stackspin version 2.2.
+    # This checks whether we need to prepare the database to follow that
+    # change.
+    migration_reset.reset()
+flask_migrate.Migrate(app, db)
+try:
+    with app.app_context():
+        flask_migrate.upgrade()
+except Exception as e:
+    app.logger.info(f"upgrade failed: {type(e)}: {e}")
+    sys.exit(2)
 
 # We need this app context in order to talk the database, which is managed by
 # flask-sqlalchemy, which assumes a flask app context.
diff --git a/backend/migration_reset.py b/backend/migration_reset.py
new file mode 100644
index 0000000000000000000000000000000000000000..4f674c75ecff4e31ccf744818978580270e4ef48
--- /dev/null
+++ b/backend/migration_reset.py
@@ -0,0 +1,34 @@
+from sqlalchemy import exc
+
+from database import db
+import logging
+
+# We "reset" the alembic version history for Stackspin 2.2, to clean up our old
+# mess of database migrations a bit, and in particular to make the transition
+# easier to moving the source of truth for some of the data (list of apps) out
+# of the database and into configmaps. This function deals with older clusters
+# that have to be led through this transition. To determine if we need to do
+# anything, we look at the `alembic_version` value in the database. If it's a
+# legacy version, we delete the table so the alembic migration will view the
+# database as "empty" and perform all new migrations on it. The new initial
+# migration will have to handle that case specially, by checking if any tables
+# already exist, and not do anything in that case.
+def reset():
+    logging.info("Checking if alembic version needs to be reset.")
+    version = None
+    try:
+        result = db.session.execute("select version_num from alembic_version")
+        for row in result:
+            version = row[0]
+    except exc.ProgrammingError:
+        # We assume this means the alembic_version table doesn't exist, which
+        # is expected for new clusters.
+        pass
+    logging.info(f"alembic version: {version}")
+    legacy_versions = ["fc0892d07771", "3fa0c38ea1ac", "e08df0bef76f", "b514cca2d47b", "5f462d2d9d25", "27761560bbcb"]
+    if version in legacy_versions:
+        logging.info("This is an old version: resetting.")
+        db.session.execute("drop table alembic_version")
+    else:
+        logging.info("This is not a known legacy version: not resetting.")
+        
diff --git a/backend/migrations/alembic.ini b/backend/migrations/alembic.ini
index ec9d45c26a6bb54e833fd4e6ce2de29343894f4b..ef355cdd0bc77377516a78e5f891f20b8573b403 100644
--- a/backend/migrations/alembic.ini
+++ b/backend/migrations/alembic.ini
@@ -8,43 +8,3 @@
 # the 'revision' command, regardless of autogenerate
 # revision_environment = false
 
-
-# Logging configuration
-[loggers]
-keys = root,sqlalchemy,alembic,flask_migrate
-
-[handlers]
-keys = console
-
-[formatters]
-keys = generic
-
-[logger_root]
-level = WARN
-handlers = console
-qualname =
-
-[logger_sqlalchemy]
-level = WARN
-handlers =
-qualname = sqlalchemy.engine
-
-[logger_alembic]
-level = INFO
-handlers =
-qualname = alembic
-
-[logger_flask_migrate]
-level = INFO
-handlers =
-qualname = flask_migrate
-
-[handler_console]
-class = StreamHandler
-args = (sys.stderr,)
-level = NOTSET
-formatter = generic
-
-[formatter_generic]
-format = %(levelname)-5.5s [%(name)s] %(message)s
-datefmt = %H:%M:%S
diff --git a/backend/migrations/env.py b/backend/migrations/env.py
index 68feded2a040005310d770ac7136b2e4ff8a6312..2a7628b80babbf6b5a2777efe7e02c5c115c391c 100644
--- a/backend/migrations/env.py
+++ b/backend/migrations/env.py
@@ -13,7 +13,9 @@ config = context.config
 
 # Interpret the config file for Python logging.
 # This line sets up loggers basically.
-fileConfig(config.config_file_name)
+# We commented this out, because we want to configure logging in the app
+# itself, not here.
+# fileConfig(config.config_file_name)
 logger = logging.getLogger('alembic.env')
 
 # add your model's MetaData object here