diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014 Rodrigo Setti
+
+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/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/io-throttle.cabal b/io-throttle.cabal
new file mode 100644
--- /dev/null
+++ b/io-throttle.cabal
@@ -0,0 +1,38 @@
+name          : io-throttle
+version       : 0.1.0
+synopsis      : Limit number of IO actions started per second
+homepage      : http://github.com/rodrigosetti/io-throttle
+license       : MIT
+license-file  : LICENSE
+copyright     : (c) 2014, Rodrigo Setti
+author        : Rodrigo Setti
+maintainer    : rodrigosetti@gmail.com
+category      : Concurrency
+build-type    : Simple
+cabal-version : >=1.10
+description   :
+     Limit the number of tasks started per second. The throttle function will
+     run all actions concurrently but only starting a certain number per
+     second. It will wait for all tasks and return the results in a list.
+
+source-repository head
+  type     : git
+  location : git@github.com:rodrigosetti/io-throttle.git
+
+library
+  exposed-modules  : Control.Concurrent.Throttle
+  build-depends    : base          == 4.*
+                   , threads       == 0.5.*
+                   , SafeSemaphore == 0.10.*
+  hs-source-dirs   : src
+  default-language : Haskell2010
+  ghc-options      : -Wall
+
+test-suite test-io-threads
+    default-language : Haskell2010
+    hs-source-dirs   : test
+    main-is          : Main.hs
+    type             : exitcode-stdio-1.0
+    build-depends    : base       == 4.*
+                     , io-throttle
+
diff --git a/src/Control/Concurrent/Throttle.hs b/src/Control/Concurrent/Throttle.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/Throttle.hs
@@ -0,0 +1,33 @@
+{-|
+Module      : Control.Concurrent.Throttle
+Description : Limit the number of IO actions per second
+Copyright   : (c) 2014, Rodrigo Setti
+License     : MIT
+Maintainer  : rodrigosetti@gmail.com
+Stability   : experimental
+Portability : POSIX
+-}
+module Control.Concurrent.Throttle (throttle) where
+
+import           Control.Concurrent
+import           Control.Concurrent.MSemN
+import qualified Control.Concurrent.Thread as Thread
+import           Control.Exception
+import           Control.Monad
+
+-- | Limit the number of @tasks@ started per second. @throttle@ will run all
+--   actions concurrently but only starting a certain number per second. It
+--   will wait for all tasks and return the results in a list.
+throttle :: Int     -- ^ number of tasks per second (TPS)
+         -> [IO a]  -- ^ the tasks to run concurrently but limited by TPS
+         -> IO [a]  -- ^ the tasks results
+throttle tps tasks =
+    do sem   <- new tps
+       let runTask task    = liftM snd $ wait sem 1 >> Thread.forkIO task
+           timeResetWorker = forever $ threadDelay 1000000 >> signalF sem (\i -> (tps-i, ()))
+           runAllTasks     = mapM runTask tasks
+       mapM Thread.result =<< sequence =<< bracket (forkIO timeResetWorker)
+                                                   killThread
+                                                   (const runAllTasks)
+
+
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,17 @@
+module Main where
+
+import Control.Concurrent
+import Control.Concurrent.Throttle
+import Control.Monad
+
+main :: IO ()
+main = do res <- throttle 5 tasks
+          putStrLn "-------------"
+          forM_ res print
+  where
+    tasks = map performTask ([1..100] :: [Int])
+    performTask i = do putStrLn $ "task start " ++ show i
+                       threadDelay $ i * 10000
+                       putStrLn $ "task done " ++ show i
+                       return i
+
