diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2022 Andre Marianiello
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE DisambiguateRecordFields #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+module Main where
+
+import Control.Monad
+import Control.Monad.IO.Unlift
+import Control.Monad.Trans.Resource
+import Control.Monad.Error.Class
+import Data.Function
+import Data.Foldable
+import Data.Int
+import Data.Text
+import Hasql.Connection
+import qualified Hasql.Decoders as Decoders
+import Hasql.Encoders
+import Hasql.Session
+import Hasql.Statement
+import Hasql.Transaction
+import qualified Hasql.Transaction.Sessions as Transaction
+import Hasql.TH
+import GHC.Generics
+
+import Hasql.TransactionIO
+import Hasql.TransactionIO.Sessions
+import Hasql.CursorTransactionIO
+import Hasql.CursorTransactionIO.TransactionIO
+
+import Hasql.Conduit
+import Hasql.Streamly
+import Hasql.Streaming
+import Hasql.Pipes
+
+import qualified Streamly.Prelude as Streamly
+import Streaming hiding (run)
+import qualified Streaming.Prelude as Streaming
+import Conduit
+import qualified Data.Conduit.Combinators as Conduit
+import Pipes hiding (each)
+import qualified Pipes.Prelude as Pipes
+
+import Rel8
+
+data Author f = Author
+  { authorId :: Column f AuthorId
+  , name :: Column f Text
+  , url :: Column f (Maybe Text)
+  }
+  deriving stock (Generic)
+  deriving anyclass (Rel8able)
+
+deriving stock instance f ~ Result => Show (Author f)
+deriving stock instance f ~ Result => Show (Project f)
+
+newtype AuthorId = AuthrId { toInt64 :: Int64 }
+  deriving newtype (DBEq, DBType, Eq, Show)
+
+data Project f = Project
+  { projectAuthorId :: Column f AuthorId
+  , projectName :: Column f Text
+  }
+  deriving stock (Generic)
+  deriving anyclass (Rel8able)
+
+authorSchema :: TableSchema (Author Name)
+authorSchema = TableSchema
+  { name = "author"
+  , schema = Nothing
+  , columns = Author
+    { authorId = "author_id"
+    , name = "name"
+    , url = "url"
+    }
+  }
+
+projectSchema :: TableSchema (Project Name)
+projectSchema = TableSchema
+  { name = "project"
+  , schema = Nothing
+  , columns = Project
+    { projectAuthorId = "author_id"
+    , projectName = "name"
+    }
+  }
+
+
+main :: IO ()
+main = do
+  let config = settings "localhost" 5432 "postgres" "password" "postgres"
+  conn <- either (error . show) id <$> acquire config
+  res <- flip run conn $ do
+    Transaction.transaction Transaction.ReadCommitted Transaction.Write $ Hasql.Transaction.sql [uncheckedSql|
+      drop table if exists author cascade;
+      create table author (
+        author_id integer not null,
+        name text not null,
+        url text,
+        primary key(author_id)
+      );
+      insert into author values
+        (1, 'Ollie'),
+        (2, 'Bryan O''Sullivan'),
+        (3, 'Emily Pilmore');
+      drop table if exists project cascade;
+      create table project (
+        author_id integer not null,
+        name text not null,
+        constraint fk_author foreign key(author_id) references author(author_id)
+      );
+      insert into project values
+        (1, 'rel8'),
+        (2, 'aeson'),
+        (2, 'text');
+    |]
+    let stmt = select (each projectSchema)
+    -- io
+    Hasql.Session.statement () stmt >>= mapM_ (liftIO . print)
+    -- streamly
+    transactionIO ReadCommitted ReadOnly NotDeferrable $
+      cursorTransactionIO $
+        streamlyQuery stmt ()
+          & Streamly.mapM_ (liftIO . print)
+    -- streaming
+    transactionIO ReadCommitted ReadOnly NotDeferrable $
+      cursorTransactionIO $
+        streamingQuery stmt ()
+          & Streaming.mapM_ (liftIO . print)
+    -- conduit
+    transactionIO ReadCommitted ReadOnly NotDeferrable $
+      cursorTransactionIO $
+        conduitQuery stmt ()
+          .| Conduit.mapM_ (liftIO . print)
+          & runConduit
+    -- pipes
+    transactionIO ReadCommitted ReadOnly NotDeferrable $
+      cursorTransactionIO $
+        pipesQuery stmt ()
+          >-> Pipes.mapM_ (liftIO . print)
+          & runEffect
+    -- concurrent cursors
+    transactionIO ReadCommitted ReadOnly NotDeferrable $ do
+      cursorTransactionIO $ do
+        cursor1 <- declareCursorFor () stmt
+        cursor2 <- declareCursorFor () stmt
+        let 
+          loop = do
+            batch1 <- fetchWithCursor cursor1
+            batch2 <- fetchWithCursor cursor2
+            unless (Prelude.null batch1 && Prelude.null batch2) $ do
+              liftIO $ print batch1
+              liftIO $ print batch2
+              loop
+        loop
+    -- concurrent streams
+    transactionIO ReadCommitted ReadOnly NotDeferrable $
+      cursorTransactionIO $ do
+        let s = streamlyQuery stmt ()
+        Streamly.zipWith (,) s s
+          & Streamly.mapM_ (liftIO . print)
+  print res
diff --git a/hasql-streams-example.cabal b/hasql-streams-example.cabal
new file mode 100644
--- /dev/null
+++ b/hasql-streams-example.cabal
@@ -0,0 +1,41 @@
+cabal-version: 2.4
+name:          hasql-streams-example
+version:       0.1.0.0
+synopsis:
+  An example program that shows how to use Hasql streams with Rel8
+
+homepage:      https://github.com/andremarianiello/hasql-streams
+bug-reports:   https://github.com/andremarianiello/hasql-streams/issues
+license:       MIT
+license-file:  LICENSE
+author:        Andre Marianiello
+maintainer:    andremarianiello@users.noreply.github.com
+copyright:     (c) 2022, Andre Marianiello
+category:      Database, PostgreSQL, Hasql, Streaming
+
+executable hasql-streaming
+  main-is:          Main.hs
+  build-depends:
+    , base                  >=4.14    && <4.17
+    , bytestring
+    , conduit
+    , hasql
+    , hasql-streams-conduit
+    , hasql-streams-pipes
+    , hasql-streams-streaming
+    , hasql-streams-streamly
+    , hasql-th
+    , hasql-transaction
+    , hasql-transaction-io
+    , mtl
+    , pipes
+    , rel8                  ^>=1.2.1.0
+    , resourcet
+    , safe-exceptions
+    , streaming
+    , streamly
+    , text
+    , unliftio-core
+
+  hs-source-dirs:   app
+  default-language: Haskell2010
