diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
-## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.0.4...main)
+## [_Unreleased_](https://github.com/freckle/freckle-app/compare/v1.0.1.0...main)
 
-None.
+- None.
+
+## [v1.0.1.0](https://github.com/freckle/freckle-app/compare/v1.0.0.4...v1.0.1.0)
+
+- Added `Freckle.App.Datadog.Gauge` for client side stateful gauges.
+- Added `Freckle.App.Datadog.Rts` for sending RTS statistics to DataDog.
 
 ## [v1.0.0.4](https://github.com/freckle/freckle-app/compare/v1.0.0.3...v1.0.0.4)
 
diff --git a/freckle-app.cabal b/freckle-app.cabal
--- a/freckle-app.cabal
+++ b/freckle-app.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.12
 name:               freckle-app
-version:            1.0.0.4
+version:            1.0.1.0
 license:            MIT
 license-file:       LICENSE
 maintainer:         Freckle Education
@@ -28,6 +28,8 @@
         Freckle.App
         Freckle.App.Database
         Freckle.App.Datadog
+        Freckle.App.Datadog.Gauge
+        Freckle.App.Datadog.Rts
         Freckle.App.Env
         Freckle.App.Env.Internal
         Freckle.App.Ghci
@@ -69,6 +71,7 @@
         data-default >=0.7.1.1,
         datadog >=0.2.5.0,
         doctest >=0.17,
+        ekg-core >=0.1.1.7,
         errors >=2.3.0,
         exceptions >=0.10.4,
         fast-logger >=3.0.5,
@@ -104,6 +107,7 @@
         transformers-base >=0.4.5.2,
         unliftio >=0.2.18,
         unliftio-core >=0.2.0.1,
+        unordered-containers >=0.2.14.0,
         wai >=3.2.3,
         wai-extra >=3.1.6,
         yaml >=0.11.5.0,
diff --git a/library/Freckle/App/Datadog.hs b/library/Freckle/App/Datadog.hs
--- a/library/Freckle/App/Datadog.hs
+++ b/library/Freckle/App/Datadog.hs
@@ -16,7 +16,7 @@
   -- * Higher-level operations
   , increment
   , counter
-  , guage
+  , gauge
   , histogram
   , histogramSince
   , histogramSinceMs
@@ -27,9 +27,11 @@
   , envParseDogStatsSettings
   , envParseDogStatsTags
   , mkStatsClient
-  )
-where
 
+  -- * To be removed in next major bump
+  , guage
+  ) where
+
 import Prelude
 
 import Control.Lens (set)
@@ -78,6 +80,20 @@
   -> m ()
 counter name tags = sendAppMetricWithTags name tags Counter
 
+gauge
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Text
+  -> [(Text, Text)]
+  -> Double
+  -> m ()
+gauge name tags = sendAppMetricWithTags name tags Gauge
+
+{-# DEPRECATED guage "Use gauge instead" #-}
+-- | Deprecated typo version of 'gauge'
 guage
   :: ( MonadUnliftIO m
      , MonadReader env m
@@ -88,7 +104,7 @@
   -> [(Text, Text)]
   -> Double
   -> m ()
-guage name tags = sendAppMetricWithTags name tags Gauge
+guage = gauge
 
 histogram
   :: ( MonadUnliftIO m
diff --git a/library/Freckle/App/Datadog/Gauge.hs b/library/Freckle/App/Datadog/Gauge.hs
new file mode 100644
--- /dev/null
+++ b/library/Freckle/App/Datadog/Gauge.hs
@@ -0,0 +1,90 @@
+-- | Stateful gauges for Datadog
+module Freckle.App.Datadog.Gauge
+  ( Gauge
+  , new
+  , increment
+  , decrement
+  , add
+  , subtract
+  ) where
+
+import Prelude hiding (subtract)
+
+import Control.Monad.IO.Unlift (MonadUnliftIO)
+import Control.Monad.Reader
+import Data.Int (Int64)
+import Data.Text (Text)
+import Freckle.App.Datadog (HasDogStatsClient, HasDogStatsTags, gauge)
+import qualified System.Metrics.Gauge as EKG
+
+-- | A data type containing all reporting values for a gauge
+data Gauge = Gauge
+  { name :: Text
+  , tags :: [(Text, Text)]
+  , ekgGauge :: EKG.Gauge
+  }
+
+-- | Create a gauge holding in memory state
+new :: MonadIO m => Text -> [(Text, Text)] -> m Gauge
+new name tags = Gauge name tags <$> liftIO EKG.new
+
+-- | Increment gauge state and report its current value
+increment
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Gauge
+  -> m ()
+increment = add 1
+
+-- | Add to gauge state and report its current value
+add
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Int64
+  -> Gauge
+  -> m ()
+add i = withEKGGauge (`EKG.add` i)
+
+-- | Decrement gauge state and report its current value
+decrement
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Gauge
+  -> m ()
+decrement = subtract 1
+
+-- | Subtract from gauge state and report its current value
+subtract
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Int64
+  -> Gauge
+  -> m ()
+subtract i = withEKGGauge (`EKG.subtract` i)
+
+withEKGGauge
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => (EKG.Gauge -> IO ())
+  -> Gauge
+  -> m ()
+withEKGGauge f Gauge {..} = do
+  current <- liftIO $ do
+    f ekgGauge
+    EKG.read ekgGauge
+  gauge name tags $ fromIntegral current
diff --git a/library/Freckle/App/Datadog/Rts.hs b/library/Freckle/App/Datadog/Rts.hs
new file mode 100644
--- /dev/null
+++ b/library/Freckle/App/Datadog/Rts.hs
@@ -0,0 +1,62 @@
+-- | RTS statistics sent to Datadog
+module Freckle.App.Datadog.Rts
+  ( forkRtsStatPolling
+  ) where
+
+import Prelude
+
+import qualified Control.Immortal as Immortal
+import Control.Monad (void)
+import Control.Monad.IO.Unlift (MonadUnliftIO, liftIO)
+import Control.Monad.Reader (MonadReader)
+import Data.Foldable (traverse_)
+import qualified Data.HashMap.Strict as HashMap
+import Data.Text (Text)
+import Freckle.App.Datadog (HasDogStatsClient, HasDogStatsTags)
+import qualified Freckle.App.Datadog as Datadog
+import qualified System.Metrics as Ekg
+import qualified System.Metrics.Distribution.Internal as Ekg
+import UnliftIO.Concurrent (threadDelay)
+
+-- | Initialize a thread to poll RTS stats
+--
+-- Stats are collected via `ekg-core` and 'System.Metrics.registerGcMetrics'
+--
+forkRtsStatPolling
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => m ()
+forkRtsStatPolling = do
+  store <- liftIO Ekg.newStore
+  liftIO $ Ekg.registerGcMetrics store
+
+  void $ Immortal.create $ \_ -> do
+    sample <- liftIO $ Ekg.sampleAll store
+    traverse_ (uncurry flushEkgSample) $ HashMap.toList sample
+
+    let seconds n = n * 1000000
+    threadDelay $ seconds 1
+
+flushEkgSample
+  :: ( MonadUnliftIO m
+     , MonadReader env m
+     , HasDogStatsClient env
+     , HasDogStatsTags env
+     )
+  => Text
+  -> Ekg.Value
+  -> m ()
+flushEkgSample name = \case
+  Ekg.Counter n -> Datadog.counter name [] $ fromIntegral n
+  Ekg.Gauge n -> Datadog.gauge name [] $ fromIntegral n
+  Ekg.Distribution d -> do
+    Datadog.gauge (name <> "." <> "mean") [] $ Ekg.mean d
+    Datadog.gauge (name <> "." <> "variance") [] $ Ekg.variance d
+    Datadog.gauge (name <> "." <> "sum") [] $ Ekg.sum d
+    Datadog.gauge (name <> "." <> "min") [] $ Ekg.min d
+    Datadog.gauge (name <> "." <> "max") [] $ Ekg.max d
+    Datadog.counter (name <> "." <> "count") [] $ fromIntegral $ Ekg.count d
+  Ekg.Label _ -> pure ()
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,6 +1,6 @@
 ---
 name: freckle-app
-version: 1.0.0.4
+version: 1.0.1.0
 maintainer: Freckle Education
 category: Utils
 github: freckle/freckle-app
@@ -60,6 +60,7 @@
     - data-default
     - datadog
     - doctest
+    - ekg-core
     - errors
     - exceptions
     - fast-logger
@@ -95,6 +96,7 @@
     - transformers-base
     - unliftio
     - unliftio-core
+    - unordered-containers
     - wai
     - wai-extra
     - yaml
