diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, Sean Parsons
+
+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 Sean Parsons 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/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/glue-common.cabal b/glue-common.cabal
new file mode 100644
--- /dev/null
+++ b/glue-common.cabal
@@ -0,0 +1,59 @@
+name:                   glue-common
+version:                0.4.1
+synopsis:               Make better services.
+description:            Common types and base functions used in the glue family of libraries. 
+license:                BSD3
+license-file:           LICENSE
+author:                 Sean Parsons
+maintainer:             github@futurenotfound.com
+category:               Network
+build-type:             Simple
+cabal-version:          >=1.10
+
+source-repository head
+  type:                 git
+  location:             git://github.com/seanparsons/glue.git
+
+library
+  exposed-modules:      Glue.Types
+  -- other-extensions:
+  build-depends:        base >=4.6 && <4.9,
+                        transformers,
+                        transformers-base,
+                        lifted-base,
+                        time,
+                        monad-control,
+                        unordered-containers,
+                        hashable,
+                        text
+  ghc-options:          -rtsopts
+                        -Wall
+  hs-source-dirs:       src
+  default-language:     Haskell2010
+
+test-suite glue-common-tests
+  build-depends:        base ==4.*,
+                        QuickCheck -any,
+                        quickcheck-instances,
+                        hspec >=2.1.10,
+                        transformers,
+                        transformers-base,
+                        lifted-base,
+                        time,
+                        monad-control,
+                        unordered-containers,
+                        hashable,
+                        ekg-core,
+                        text,
+                        async
+  other-modules:        Spec
+  ghc-options:          -rtsopts
+                        -Wall
+                        -O2
+                        -threaded
+  type:                 exitcode-stdio-1.0
+  main-is:              Main.hs
+  buildable:            True
+  default-language:     Haskell2010
+  hs-source-dirs:       test,
+                        src
diff --git a/src/Glue/Types.hs b/src/Glue/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Glue/Types.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- | Module containing the root types and some support functionality.
+module Glue.Types(
+    BasicService
+  , MultiGetService
+  , MultiGetRequest
+  , MultiGetResponse
+  , ResultVar
+  , MToIO
+  , FailOrSuccess
+  , multiGetToBasic
+  , basicToMultiGet
+  , getResult
+  , makeCall
+) where
+
+import Control.Applicative
+import Data.Hashable
+import Control.Concurrent
+import qualified Control.Concurrent.MVar.Lifted as MV
+import Control.Exception.Base hiding(throw, throwIO, catch)
+import Control.Exception.Lifted hiding(throw)
+import Control.Monad.Trans.Control
+import qualified Data.HashSet as S
+import qualified Data.HashMap.Strict as M
+
+-- | Type alias for the most basic form of a service supported.
+type BasicService m a b = a -> m b
+-- | Type alias for the request portion of a `MultiGetService`.
+type MultiGetRequest a = S.HashSet a
+-- | Type alias for the response portion of a `MultiGetService`.
+type MultiGetResponse a b = M.HashMap a b
+-- | Type alias for a service that looks up multiple values and returns multiple results.
+type MultiGetService m a b = BasicService m (MultiGetRequest a) (MultiGetResponse a b)
+-- | Type alias for the common container of a result used in asynchronous calls.
+type ResultVar a = MVar (Either SomeException a)
+-- | Run the m into an IO instance for a response.
+type MToIO m = forall a. m a -> IO a
+-- | Type alias for either a failure or a successful response.
+type FailOrSuccess a b = Either SomeException (MultiGetResponse a b)
+
+-- | Convert a 'MultiGetService' into a 'BasicService' that looks up a single key, returning a `Maybe` which determines if the value was present.
+multiGetToBasic :: (Hashable a, Eq a, Monad m) => MultiGetService m a b -> BasicService m a (Maybe b)
+multiGetToBasic service = (\r -> do
+  mapResult <- service (S.singleton r)
+  return $ M.lookup r mapResult)
+
+-- | Convert a 'BasicService' into a 'MultiGetService'
+basicToMultiGet :: (Hashable a, Eq a, Applicative m) => BasicService m a b -> MultiGetService m a b
+basicToMultiGet service =
+  let callService resultMap request = liftA2 (flip $ M.insert request) resultMap (service request)
+  in  S.foldl' callService (pure M.empty)
+
+-- | Obtain a result from a 'ResultVar' in the 'Monad' of your choice.
+getResult :: (MonadBaseControl IO m) => ResultVar a -> m a
+getResult var = do
+  result <- MV.readMVar var
+  either throwIO return result
+
+-- | Makes a multi-get call and handles the error bundling it up inside an 'Either'.
+makeCall :: (Eq a, Hashable a, MonadBaseControl IO m) => MultiGetService m a b -> S.HashSet a -> m (FailOrSuccess a b)
+makeCall service requests = catch (fmap Right $ service requests) (\(e :: SomeException) -> return $ Left e)
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,14 @@
+module Main where
+
+import Test.Hspec.Runner
+import qualified Spec
+
+customConfig :: Config
+customConfig = defaultConfig 
+  { configColorMode       = ColorAlways
+  , configPrintCpuTime    = True
+  }
+
+
+main :: IO ()
+main = hspecWith customConfig Spec.spec
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-}
