diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 # Changelog for persistent-mysql
 
+## 2.10.2.1
+
+* Changed persistent-mysql to use 'utf8mb4' instead of 'utf8' in migrations [#980](https://github.com/yesodweb/persistent/pull/980) @charukiewicz
+
 ## 2.10.2
 
 * Added support for GHC 8.8 [#977](https://github.com/yesodweb/persistent/pull/977)
diff --git a/Database/Persist/MySQL.hs b/Database/Persist/MySQL.hs
--- a/Database/Persist/MySQL.hs
+++ b/Database/Persist/MySQL.hs
@@ -767,9 +767,9 @@
 showSqlType SqlInt64   _          _     = "BIGINT"
 showSqlType SqlReal    _          _     = "DOUBLE"
 showSqlType (SqlNumeric s prec) _ _     = "NUMERIC(" ++ show s ++ "," ++ show prec ++ ")"
-showSqlType SqlString  Nothing    True  = "TEXT CHARACTER SET utf8"
+showSqlType SqlString  Nothing    True  = "TEXT CHARACTER SET utf8mb4"
 showSqlType SqlString  Nothing    False = "TEXT"
-showSqlType SqlString  (Just i)   True  = "VARCHAR(" ++ show i ++ ") CHARACTER SET utf8"
+showSqlType SqlString  (Just i)   True  = "VARCHAR(" ++ show i ++ ") CHARACTER SET utf8mb4"
 showSqlType SqlString  (Just i)   False = "VARCHAR(" ++ show i ++ ")"
 showSqlType SqlTime    _          _     = "TIME"
 showSqlType (SqlOther t) _        _     = T.unpack t
diff --git a/persistent-mysql.cabal b/persistent-mysql.cabal
--- a/persistent-mysql.cabal
+++ b/persistent-mysql.cabal
@@ -1,5 +1,5 @@
 name:            persistent-mysql
-version:         2.10.2
+version:         2.10.2.1
 license:         MIT
 license-file:    LICENSE
 author:          Felipe Lessa <felipe.lessa@gmail.com>, Michael Snoyman
@@ -56,6 +56,7 @@
     hs-source-dirs:  test
     other-modules:   MyInit
                      InsertDuplicateUpdate
+                     CustomConstraintTest
     ghc-options:     -Wall
 
     build-depends:   base             >= 4.9 && < 5
diff --git a/test/CustomConstraintTest.hs b/test/CustomConstraintTest.hs
new file mode 100644
--- /dev/null
+++ b/test/CustomConstraintTest.hs
@@ -0,0 +1,47 @@
+{-# LANGUAGE EmptyDataDecls             #-}
+{-# LANGUAGE FlexibleContexts           #-}
+{-# LANGUAGE GADTs                      #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE QuasiQuotes                #-}
+{-# LANGUAGE TemplateHaskell            #-}
+{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE UndecidableInstances       #-}
+{-# LANGUAGE DerivingStrategies         #-}
+{-# LANGUAGE StandaloneDeriving         #-}
+module CustomConstraintTest where
+
+import MyInit
+import qualified Data.Text as T
+
+share [mkPersist sqlSettings, mkMigrate "customConstraintMigrate"] [persistLowerCase|
+CustomConstraint1
+    some_field Text
+    deriving Show
+
+CustomConstraint2
+    cc_id CustomConstraint1Id constraint=custom_constraint
+    deriving Show
+|]
+
+specs :: (MonadIO m, MonadFail m) => RunDb SqlBackend m -> Spec
+specs runDb = do
+  describe "custom constraint used in migration" $ do
+    it "custom constraint is actually created" $ runDb $ do
+      runMigration customConstraintMigrate
+      runMigration customConstraintMigrate -- run a second time to ensure the constraint isn't dropped
+      let query = T.concat ["SELECT COUNT(*) "
+                           ,"FROM information_schema.key_column_usage "
+                           ,"WHERE ordinal_position=1 "
+                           ,"AND referenced_table_name=? "
+                           ,"AND referenced_column_name=? "
+                           ,"AND table_name=? "
+                           ,"AND column_name=? "
+                           ,"AND constraint_name=?"]
+      [Single exists] <- rawSql query [PersistText "custom_constraint1"
+                                      ,PersistText "id"
+                                      ,PersistText "custom_constraint2"
+                                      ,PersistText "cc_id"
+                                      ,PersistText "custom_constraint"]
+      liftIO $ 1 @?= (exists :: Int)
diff --git a/test/InsertDuplicateUpdate.hs b/test/InsertDuplicateUpdate.hs
--- a/test/InsertDuplicateUpdate.hs
+++ b/test/InsertDuplicateUpdate.hs
@@ -5,6 +5,8 @@
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE StandaloneDeriving #-}
 
 module InsertDuplicateUpdate where
 
diff --git a/test/main.hs b/test/main.hs
--- a/test/main.hs
+++ b/test/main.hs
@@ -5,6 +5,9 @@
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# OPTIONS_GHC -Wno-unused-top-binds #-}
 
 import MyInit
@@ -45,6 +48,7 @@
 import qualified TransactionLevelTest
 import qualified UniqueTest
 import qualified UpsertTest
+import qualified CustomConstraintTest
 
 type Tuple a b = (a, b)
 
@@ -179,6 +183,7 @@
     TransactionLevelTest.specsWith db
 
     MigrationIdempotencyTest.specsWith db
+    CustomConstraintTest.specs db
 
 roundFn :: RealFrac a => a -> Integer
 roundFn = round
