diff --git a/network-metrics.cabal b/network-metrics.cabal
--- a/network-metrics.cabal
+++ b/network-metrics.cabal
@@ -1,5 +1,5 @@
 name:               network-metrics
-version:            0.1.0
+version:            0.1.1
 synopsis:           Send metrics to Ganglia, Graphite, and statsd.
 license:            OtherLicense
 license-file:       LICENSE
@@ -35,6 +35,7 @@
   exposed-modules:  Network.Metrics.Ganglia
                   , Network.Metrics.Graphite
                   , Network.Metrics.Statsd
+  other-modules:    Network.Metrics.Internal
 
   hs-source-dirs:   src
 
diff --git a/src/Network/Metrics/Internal.hs b/src/Network/Metrics/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Metrics/Internal.hs
@@ -0,0 +1,53 @@
+-- |
+-- Module      : Network.Metrics.Internal
+-- Copyright   : (c) 2012 Brendan Hay <brendan@soundcloud.com>
+-- License     : This Source Code Form is subject to the terms of
+--               the Mozilla Public License, v. 2.0.
+--               A copy of the MPL can be found in the LICENSE file or
+--               you can obtain it at http://mozilla.org/MPL/2.0/.
+-- Maintainer  : Brendan Hay <brendan@soundcloud.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+--
+
+module Network.Metrics.Internal (
+    -- * Exported types
+      Handle(..)
+
+    -- * Socket Handle operations
+    , open
+    , close
+    , emit
+    ) where
+
+import Control.Monad                  (unless)
+import Network.Socket                 hiding (send)
+import Network.Socket.ByteString.Lazy (send)
+
+import qualified Data.ByteString.Lazy.Char8 as BL
+
+-- | Socket handle
+data Handle = Handle Socket SockAddr deriving (Show)
+
+--
+-- API
+--
+
+-- | Create a new unconnected socket handle for UDP communication
+open :: SocketType -> String -> String -> IO Handle
+open typ host port = do
+    (addr:_) <- getAddrInfo Nothing (Just host) (Just port)
+    sock     <- socket (addrFamily addr) typ defaultProtocol
+    return $ Handle sock (addrAddress addr)
+
+-- | Close a socket handle
+close :: Handle -> IO ()
+close (Handle sock _) = sClose sock
+
+-- | Push an encoded metric to the specified socket handle
+emit :: BL.ByteString -> Handle -> IO Handle
+emit bstr handle@(Handle sock addr) | BL.null bstr = return handle
+                                    | otherwise    = do
+    sIsConnected sock >>= \b -> unless b $ connect sock addr
+    _ <- send sock bstr
+    return handle
