diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Ilya Murzinov (c) 2017
+
+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.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"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
+OWNER OR CONTRIBUTORS 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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# postgres-embedded
+
+Haskell API for starting/stopping embedded PostgreSQL instance.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/postgres-embedded.cabal b/postgres-embedded.cabal
new file mode 100644
--- /dev/null
+++ b/postgres-embedded.cabal
@@ -0,0 +1,42 @@
+name:                postgres-embedded
+version:             0.1.0
+description:         Library for easily running embedded PostgreSQL server for tests
+homepage:            https://github.com/ilya-murzinov/postgres-embedded
+license:             MIT
+license-file:        LICENSE
+author:              Ilya Murzinov
+maintainer:          murz42@gmail.com
+copyright:           2017 Ilya Murzinov
+category:            Lib
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Database.PostgreSQL.Embedded
+  other-modules:       Database.PostgreSQL.Embedded.Postgres
+                     , Database.PostgreSQL.Embedded.Download
+                     , Database.PostgreSQL.Embedded.Types
+  build-depends:       base >= 4.7 && < 5
+                     , directory
+                     , filepath
+                     , shell-conduit
+                     , HDBC
+                     , HDBC-postgresql
+  ghc-options:         -Wall
+  default-language:    Haskell2010
+
+test-suite postgres-embedded-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , postgres-embedded
+                     , filepath
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: git://github.com/ilya-murzinov/postgres-embedded.git
diff --git a/src/Database/PostgreSQL/Embedded.hs b/src/Database/PostgreSQL/Embedded.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/PostgreSQL/Embedded.hs
@@ -0,0 +1,12 @@
+module Database.PostgreSQL.Embedded
+    ( startPostgres
+    , stopPostgres
+    , Version(..)
+    , Os(..)
+    , StartupConfig(..)
+    , RuntimeConfig(..)
+    , DBConfig(..)
+    ) where
+
+import           Database.PostgreSQL.Embedded.Postgres
+import           Database.PostgreSQL.Embedded.Types
diff --git a/src/Database/PostgreSQL/Embedded/Download.hs b/src/Database/PostgreSQL/Embedded/Download.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/PostgreSQL/Embedded/Download.hs
@@ -0,0 +1,49 @@
+module Database.PostgreSQL.Embedded.Download
+    ( downloadPostgres
+    ) where
+
+import           Data.Conduit.Shell                 (cd, run, tar, unzip', wget)
+import           Data.Monoid                        ((<>))
+import           System.Directory                   (createDirectoryIfMissing,
+                                                     doesDirectoryExist,
+                                                     getHomeDirectory)
+import           System.FilePath.Posix              ((</>))
+
+import           Database.PostgreSQL.Embedded.Types
+
+data ArchiveType = Zip | Tar deriving (Eq)
+
+downloadPostgres :: Os -> Version -> IO FilePath
+downloadPostgres os_ version_ = do
+    home <- getHomeDirectory
+
+    let v = value version_
+    let workdir = home </> ".postgres-embedded" </> v
+    let tmp = workdir </> "postgres.tmp"
+    let dist = workdir </> "pgsql"
+
+    createDirectoryIfMissing True workdir
+
+    exists <- doesDirectoryExist dist
+    case exists of
+        True -> return dist
+        False -> run $ do
+            cd workdir
+
+            let (aType, suffix) = binaries os_
+
+            wget "-O" tmp $ base_download_url <> v <> suffix
+
+            case aType of
+                Zip -> unzip' "-q" tmp
+                Tar -> tar "-xzf" tmp
+
+            return dist
+
+            where
+                binaries :: Os -> (ArchiveType, String)
+                binaries OSX   = (Zip, "-osx-binaries.zip")
+                binaries Win   = (Zip, "-windows-x64-binaries.zip")
+                binaries Linux = (Tar, "-linux-x64-binaries.tar.gz")
+
+                base_download_url = "http://get.enterprisedb.com/postgresql/postgresql-"
diff --git a/src/Database/PostgreSQL/Embedded/Postgres.hs b/src/Database/PostgreSQL/Embedded/Postgres.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/PostgreSQL/Embedded/Postgres.hs
@@ -0,0 +1,58 @@
+module Database.PostgreSQL.Embedded.Postgres
+    ( startPostgres
+    , stopPostgres
+    , checkPostgresStarted
+    ) where
+
+import           Control.Concurrent                    (threadDelay)
+import           Control.Exception                     (try)
+import           Data.Conduit.Shell                    (rm, run, shell)
+import           Data.List                             (isInfixOf)
+import           Data.Monoid                           ((<>))
+import           Database.HDBC                         (SqlError)
+import           Database.HDBC.PostgreSQL              (Connection,
+                                                        connectPostgreSQL)
+import           System.FilePath.Posix                 ((</>))
+import           System.Info                           (os)
+
+import           Database.PostgreSQL.Embedded.Download
+import           Database.PostgreSQL.Embedded.Types
+
+startPostgres :: StartupConfig -> DBConfig -> IO RuntimeConfig
+startPostgres (StartupConfig version_ t) dConfig@(DBConfig p u) = do
+    e <- downloadPostgres getOS version_
+    let d = e </> "data"
+    run $ do
+        shell $ e </> "bin" </> "initdb" <> " -A trust -U " <> u <> " -D " <> d <> " -E UTF-8"
+        shell $ e </> "bin" </> "pg_ctl" <> " -D " <> d <> " -o \"-F -p " <>
+            (show p) <> "\"" <> " -l " <> (e </> "log") <> " start"
+    checkPostgresStarted dConfig t
+    return $ RuntimeConfig e d
+    where
+        getOS | "darwin" `isInfixOf` os = OSX
+              | "linux" `isInfixOf` os = Linux
+              | "win" `isInfixOf` os = Win
+              | otherwise = error $ "Unsupported platform" <> os
+
+stopPostgres :: RuntimeConfig -> IO ()
+stopPostgres (RuntimeConfig e d) = run $ do
+        shell $ e </> "bin" </> "pg_ctl" <> " -D " <> d <> " stop"
+        rm "-rf" d
+
+checkPostgresStarted :: DBConfig -> Int -> IO ()
+checkPostgresStarted config secs = checkPostgresStarted_ config secs >>= \_ -> return ()
+    where
+        checkPostgresStarted_ :: DBConfig -> Int -> IO Bool
+        checkPostgresStarted_ (DBConfig p u) n = do
+            let connStr = "postgres://" <> u <> "@localhost:" <> (show p) <> "/postgres"
+            let oneSec = 1000000
+
+            res <- try $ connectPostgreSQL connStr :: IO (Either SqlError Connection)
+            case res of
+                Left e -> if (n > 0) then
+                    print e >>=
+                        \_ -> threadDelay oneSec >>=
+                            \_ -> checkPostgresStarted_ config (n - 1)
+                else
+                    return False
+                Right _ -> return True
diff --git a/src/Database/PostgreSQL/Embedded/Types.hs b/src/Database/PostgreSQL/Embedded/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Database/PostgreSQL/Embedded/Types.hs
@@ -0,0 +1,26 @@
+module Database.PostgreSQL.Embedded.Types
+    ( Version(..)
+    , Os(..)
+    , StartupConfig(..)
+    , RuntimeConfig(..)
+    , DBConfig(..)
+    ) where
+
+data Os = Win | OSX | Linux deriving (Eq)
+
+newtype Version = Version { value :: String }
+
+data StartupConfig = StartupConfig {
+    version        :: Version,
+    startupTimeout :: Int
+}
+
+data RuntimeConfig = RuntimeConfig {
+    execDir :: FilePath,
+    dataDir :: FilePath
+}
+
+data DBConfig = DBConfig {
+    port     :: Int,
+    username :: String
+}
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,16 @@
+import           System.Info                  as SI (os)
+
+import           Database.PostgreSQL.Embedded
+
+main :: IO ()
+main = do
+    let sConfig = StartupConfig (Version "9.6.5-1") 10
+    let dConfig = DBConfig 46782 "postgres"
+
+    -- Start Postgres downloading distribution
+    rc <- startPostgres sConfig dConfig
+    stopPostgres rc
+
+    -- Start Postgres with cached distribution
+    rc1 <- startPostgres sConfig dConfig
+    stopPostgres rc
