diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for beam-automigrate
 
+## 0.1.1.0
+
+* Escape sql identifiers only when required by the [postgres syntax rules](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS)
+
 ## 0.1.0.1
 
 * Loosen time version bounds
diff --git a/beam-automigrate.cabal b/beam-automigrate.cabal
--- a/beam-automigrate.cabal
+++ b/beam-automigrate.cabal
@@ -1,5 +1,5 @@
 name:               beam-automigrate
-version:            0.1.0.1
+version:            0.1.1.0
 license-file:       LICENSE
 build-type:         Simple
 cabal-version:      >=1.10
diff --git a/src/Database/Beam/AutoMigrate/Util.hs b/src/Database/Beam/AutoMigrate/Util.hs
--- a/src/Database/Beam/AutoMigrate/Util.hs
+++ b/src/Database/Beam/AutoMigrate/Util.hs
@@ -5,9 +5,11 @@
 
 import Control.Applicative.Lift
 import Control.Monad.Except
+import Data.Char
 import Data.Functor.Constant
 import Data.String (fromString)
 import Data.Text (Text)
+import qualified Data.Text as T
 import Database.Beam.AutoMigrate.Types (ColumnName (..), TableName (..))
 import Database.Beam.Schema (Beamable, PrimaryKey, TableEntity, TableSettings)
 import qualified Database.Beam.Schema as Beam
@@ -103,8 +105,25 @@
 sqlOptCharSet Nothing = mempty
 sqlOptCharSet (Just cs) = " CHARACTER SET " <> cs
 
+-- | Escape a sql identifier according to the rules defined in the postgres manual
 sqlEscaped :: Text -> Text
-sqlEscaped t = "\"" <> t <> "\""
+sqlEscaped t = if sqlValidUnescaped t
+  then t
+  else
+    -- Double-quotes inside identifier names must be escaped by with an additional double-quote
+    "\"" <> (T.intercalate "\"\"" $ T.splitOn "\"" t) <> "\""
+
+-- | Check whether an identifier is valid without escaping (True) or must be escaped (False)
+-- according to the postgres <https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS manual>
+sqlValidUnescaped :: Text -> Bool
+sqlValidUnescaped t = case T.uncons t of
+  Nothing -> True
+  Just (c, rest) -> validUnescapedHead c && validUnescapedTail rest
+  where
+    validUnescapedHead c = c `elem` ("1234567890_"::String) || isAlpha c
+    validUnescapedTail = all
+      (\r -> (isAlpha r && isLower r) || r `elem` ("1234567890$_"::String)) . T.unpack
+
 
 sqlSingleQuoted :: Text -> Text
 sqlSingleQuoted t = "'" <> t <> "'"
