diff --git a/Database/Persist/Postgresql.hs b/Database/Persist/Postgresql.hs
new file mode 100644
--- /dev/null
+++ b/Database/Persist/Postgresql.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE FlexibleContexts #-}
+-- | A postgresql backend for persistent.
+module Database.Persist.Postgresql
+    ( PostgresqlReader
+    , persistPostgresql
+    , runPostgresql
+    , withPostgresql
+      -- * Re-exports
+    , Connection
+    , connectPostgreSQL
+    , Int64
+    , module Database.Persist.Helper
+    , persist
+    ) where
+
+import Database.Persist (PersistValue (..))
+import Database.Persist.Helper
+import Database.Persist.GenericSql
+import Control.Monad.Trans.Reader
+import Language.Haskell.TH.Syntax hiding (lift)
+import Control.Monad.IO.Class (MonadIO (..))
+import Data.List (intercalate)
+import "MonadCatchIO-transformers" Control.Monad.CatchIO
+import qualified Database.HDBC as H
+import Database.HDBC.PostgreSQL
+import Data.Char (toLower)
+
+-- | Generate data types and instances for the given entity definitions. Can
+-- deal directly with the output of the 'persist' quasi-quoter.
+persistPostgresql :: [EntityDef] -> Q [Dec]
+persistPostgresql = fmap concat . mapM derivePersistPostgresqlReader
+
+-- | A ReaderT monad transformer holding a postgresql database connection.
+type PostgresqlReader = ReaderT Connection
+
+-- | Handles opening and closing of the database connection automatically.
+withPostgresql :: MonadCatchIO m => String -> (Connection -> m a) -> m a
+withPostgresql s f =
+    bracket (liftIO $ connectPostgreSQL s) (liftIO . H.disconnect) f
+
+-- | Run a series of database actions within a single transactions. On any
+-- exception, the transaction is rolled back.
+runPostgresql :: MonadCatchIO m => PostgresqlReader m a -> Connection -> m a
+runPostgresql r conn = do
+    res <- onException (runReaderT r conn) $ liftIO (H.rollback conn)
+    liftIO $ H.commit conn
+    return res
+
+withStmt :: MonadIO m
+         => String
+         -> [PersistValue]
+         -> (RowPopper (PostgresqlReader m) -> PostgresqlReader m a)
+         -> PostgresqlReader m a
+withStmt sql vals f = do
+    conn <- ask
+    stmt <- liftIO $ H.prepare conn sql
+    _ <- liftIO $ H.execute stmt $ map pToSql vals
+    f $ liftIO $ (fmap . fmap) (map pFromSql) $ H.fetchRow stmt
+
+execute :: MonadIO m => String -> [PersistValue] -> PostgresqlReader m ()
+execute sql vals = do
+    conn <- ask
+    stmt <- liftIO $ H.prepare conn sql
+    _ <- liftIO $ H.execute stmt $ map pToSql vals
+    return ()
+
+insert :: MonadIO m
+       => String -> [String] -> [PersistValue] -> PostgresqlReader m Int64
+insert t cols vals = do
+    let sql = "INSERT INTO " ++ t ++
+              "(" ++ intercalate "," cols ++
+              ") VALUES(" ++
+              intercalate "," (map (const "?") cols) ++ ") " ++
+              "RETURNING id"
+    withStmt sql vals $ \pop -> do
+        Just [PersistInt64 i] <- pop
+        return i
+
+tableExists :: MonadIO m => String -> PostgresqlReader m Bool
+tableExists t = do
+    conn <- ask
+    tables <- liftIO $ H.getTables conn
+    return $ map toLower t `elem` tables
+
+derivePersistPostgresqlReader :: EntityDef -> Q [Dec]
+derivePersistPostgresqlReader t = do
+    let wrap = ConT ''ReaderT `AppT` ConT ''Connection
+    gs <- [|GenericSql withStmt execute insert tableExists "SERIAL UNIQUE"|]
+    deriveGenericSql wrap gs t
+
+pToSql :: PersistValue -> H.SqlValue
+pToSql (PersistString s) = H.SqlString s
+pToSql (PersistByteString bs) = H.SqlByteString bs
+pToSql (PersistInt64 i) = H.SqlInt64 i
+pToSql (PersistDouble d) = H.SqlDouble d
+pToSql (PersistBool b) = H.SqlBool b
+pToSql (PersistDay d) = H.SqlLocalDate d
+pToSql (PersistTimeOfDay t) = H.SqlLocalTimeOfDay t
+pToSql (PersistUTCTime t) = H.SqlUTCTime t
+pToSql PersistNull = H.SqlNull
+
+pFromSql :: H.SqlValue -> PersistValue
+pFromSql (H.SqlString s) = PersistString s
+pFromSql (H.SqlByteString bs) = PersistByteString bs
+pFromSql (H.SqlWord32 i) = PersistInt64 $ fromIntegral i
+pFromSql (H.SqlWord64 i) = PersistInt64 $ fromIntegral i
+pFromSql (H.SqlInt32 i) = PersistInt64 $ fromIntegral i
+pFromSql (H.SqlInt64 i) = PersistInt64 $ fromIntegral i
+pFromSql (H.SqlInteger i) = PersistInt64 $ fromIntegral i
+pFromSql (H.SqlChar c) = PersistInt64 $ fromIntegral $ fromEnum c
+pFromSql (H.SqlBool b) = PersistBool b
+pFromSql (H.SqlDouble b) = PersistDouble b
+pFromSql (H.SqlRational b) = PersistDouble $ fromRational b
+pFromSql (H.SqlLocalDate d) = PersistDay d
+pFromSql (H.SqlLocalTimeOfDay d) = PersistTimeOfDay d
+pFromSql (H.SqlUTCTime d) = PersistUTCTime d
+pFromSql H.SqlNull = PersistNull
+pFromSql x = PersistString $ H.fromSql x -- FIXME
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+The following license covers this documentation, and the source code, except
+where otherwise indicated.
+
+Copyright 2010, Michael Snoyman. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,7 @@
+#!/usr/bin/env runhaskell
+
+> module Main where
+> import Distribution.Simple
+
+> main :: IO ()
+> main = defaultMain
diff --git a/persistent-postgresql.cabal b/persistent-postgresql.cabal
new file mode 100644
--- /dev/null
+++ b/persistent-postgresql.cabal
@@ -0,0 +1,29 @@
+name:            persistent-postgresql
+version:         0.0.0
+license:         BSD3
+license-file:    LICENSE
+author:          Michael Snoyman <michael@snoyman.com>
+maintainer:      Michael Snoyman <michael@snoyman.com>
+synopsis:        Backend for the persistent library using postgresql.
+description:     Based on the HDBC-postgresql package
+category:        Database
+stability:       Stable
+cabal-version:   >= 1.6
+build-type:      Simple
+homepage:        http://docs.yesodweb.com/persistent/
+
+library
+    build-depends:   base >= 4 && < 5,
+                     template-haskell >= 2.4 && < 2.5,
+                     HDBC >= 2.2.6 && < 2.3,
+                     transformers >= 0.2.1 && < 0.3,
+                     MonadCatchIO-transformers >= 0.2.2 && < 0.3,
+                     HDBC-postgresql >= 2.2.3.1 && < 2.3,
+                     persistent >= 0.0.0 && < 0.1
+    exposed-modules: Database.Persist.Postgresql
+    ghc-options:     -Wall
+
+source-repository head
+  type:     git
+  location: git://github.com/snoyberg/persistent.git
+
