diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@
 
 ## Unreleased
 
+## 0.2.0.0 - 2023-09-02
+
+- Fix gauges.
+
 ## 0.1.0.0 - 2023-09-02
 
 - Initial release.
diff --git a/src/System/Metrics/StatsD.hs b/src/System/Metrics/StatsD.hs
--- a/src/System/Metrics/StatsD.hs
+++ b/src/System/Metrics/StatsD.hs
@@ -19,6 +19,8 @@
     newStatSet,
     incrementCounter,
     setGauge,
+    incrementGauge,
+    decrementGauge,
     addTiming,
     newSetElement,
     withStats,
@@ -80,11 +82,11 @@
     else return Nothing
 
 newStatGauge ::
-  (MonadIO m) => Stats -> Key -> Int -> Int -> m (Maybe StatGauge)
-newStatGauge stats key sampling ini = do
+  (MonadIO m) => Stats -> Key -> Int -> m (Maybe StatGauge)
+newStatGauge stats key ini = do
   success <- newMetric stats key (GaugeData ini)
   if success
-    then return $ Just $ StatGauge stats key sampling
+    then return $ Just $ StatGauge stats key
     else return Nothing
 
 newStatTiming :: (MonadIO m) => Stats -> Key -> Int -> m (Maybe StatTiming)
@@ -106,9 +108,16 @@
   processSample stats sampling key . Counter
 
 setGauge :: (MonadIO m) => StatGauge -> Int -> m ()
-setGauge StatGauge {..} =
-  processSample stats sampling key . Gauge
+setGauge StatGauge {..} i =
+  processSample stats 1 key (Gauge i False)
 
+incrementGauge :: (MonadIO m) => StatGauge -> Int -> m ()
+incrementGauge StatGauge {..} i =
+  processSample stats 1 key (Gauge i True)
+
+decrementGauge :: (MonadIO m) => StatGauge -> Int -> m ()
+decrementGauge x i = incrementGauge x (negate i)
+
 addTiming :: (MonadIO m) => StatTiming -> Int -> m ()
 addTiming StatTiming {..} =
   processSample stats sampling key . Timing
@@ -154,7 +163,11 @@
       let s = C.unpack v
        in case t of
             "c" -> Counter <$> parseRead s
-            "g" -> Gauge <$> parseRead s
+            "g" ->
+              case s of
+                '+' : n -> Gauge <$> parseRead n <*> pure True
+                '-' : _ -> Gauge <$> parseRead s <*> pure True
+                _ -> Gauge <$> parseRead s <*> pure False
             "s" -> return $ Set s
             "ms" -> Timing <$> parseRead s
             _ -> mzero
diff --git a/src/System/Metrics/StatsD/Internal.hs b/src/System/Metrics/StatsD/Internal.hs
--- a/src/System/Metrics/StatsD/Internal.hs
+++ b/src/System/Metrics/StatsD/Internal.hs
@@ -15,7 +15,7 @@
     Gauge,
     Timing,
     SetElement,
-    TimingData,
+    Timings,
     SetData,
     MetricData (..),
     Store (..),
@@ -120,14 +120,14 @@
 
 type SetElement = String
 
-type TimingData = [Int]
+type Timings = [Int]
 
 type SetData = HashSet String
 
 data MetricData
   = CounterData !Counter
   | GaugeData !Gauge
-  | TimingData !TimingData
+  | TimingData !Timings
   | SetData !(HashSet String)
 
 data Store = Store
@@ -139,7 +139,7 @@
 
 data Value
   = Counter !Counter
-  | Gauge !Gauge
+  | Gauge !Gauge !Bool
   | Timing !Timing
   | Set !SetElement
   | Metric !Int
@@ -169,8 +169,7 @@
 
 data StatGauge = StatGauge
   { stats :: !Stats,
-    key :: !Key,
-    sampling :: !Sampling
+    key :: !Key
   }
 
 data StatTiming = StatTiming
@@ -215,7 +214,8 @@
     adjust m = m {index = m.index + 1, dat = change <$> m.dat}
     change store = case (reading, store) of
       (Counter c, CounterData s) -> CounterData (s + c)
-      (Gauge i, GaugeData _) -> GaugeData i
+      (Gauge i False, GaugeData _) -> GaugeData i
+      (Gauge i True, GaugeData g) -> GaugeData (max 0 (g + i))
       (Timing t, TimingData s) -> TimingData (t : s)
       (Set e, SetData s) -> SetData (HashSet.insert e s)
       _ -> error "Stats reading mismatch"
@@ -279,7 +279,7 @@
   GaugeData s ->
     [ Report
         { key = catKey [cfg.statsPrefix, cfg.prefixGauge, key],
-          value = Gauge s,
+          value = Gauge s False,
           rate = 1.0
         }
     ]
@@ -299,7 +299,7 @@
   }
   deriving (Eq, Ord, Show, Read)
 
-makeTimingStats :: TimingData -> TimingStats
+makeTimingStats :: Timings -> TimingStats
 makeTimingStats timings =
   TimingStats
     { timings = sorted,
@@ -316,7 +316,7 @@
     . filter (\x -> x > 0 && x < 100)
     . (.timingPercentiles)
 
-timingReports :: StatConfig -> Key -> TimingData -> [Report]
+timingReports :: StatConfig -> Key -> Timings -> [Report]
 timingReports cfg key timings =
   concatMap (timingStats cfg key tstats) percentiles
   where
@@ -432,8 +432,10 @@
       case report.value of
         Counter i ->
           printf "%d|c%s" i rate
-        Gauge g ->
+        Gauge g False ->
           printf "%d|g" g
+        Gauge g True ->
+          printf "%+d|g" g
         Timing t ->
           printf "%d|ms%s" t rate
         Set e ->
diff --git a/statsd-rupp.cabal b/statsd-rupp.cabal
--- a/statsd-rupp.cabal
+++ b/statsd-rupp.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           statsd-rupp
-version:        0.1.0.0
+version:        0.2.0.0
 synopsis:       Simple StatsD Client
 description:    Please see the README on GitHub at <https://github.com/jprupp/statsd-rupp#readme>
 category:       System
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -26,7 +26,7 @@
       Just _ <- newStatCounter stats "planets" 1
       Just _ <- newStatCounter stats "moons" 1
       return () :: Expectation
-    it "reports two counters" $ \(stats, report) -> do
+    it "reports on two counters" $ \(stats, report) -> do
       Just planets <- newStatCounter stats "planets" 1
       Just moons <- newStatCounter stats "moons" 1
       incrementCounter planets 10
@@ -50,7 +50,7 @@
       rs `shouldMatchList` rs'
       r <- report
       r.key `shouldNotBe` "moons"
-    it "reports counter stats" $ \(stats, report) -> do
+    it "reports stats" $ \(stats, report) -> do
       Just c <- newStatCounter stats "planets" 4
       replicateM_ 20 (incrementCounter c 10)
       replicateM_ 5 report
@@ -69,14 +69,14 @@
               ]
         rs `shouldMatchList` rs'
   describe "timing" $ do
-    it "reports timing events" $ \(stats, report) -> do
+    it "reports events" $ \(stats, report) -> do
       let timings = [51 .. 55]
       Just t <- newStatTiming stats "trips" 1
       forM_ timings (addTiming t)
       rs <- replicateM (length timings) report
       let rs' = map (\n -> Report "trips" (Timing n) 1.0) timings
       rs `shouldMatchList` rs'
-    it "reports empty timing stats" $ \(stats, report) -> do
+    it "reports empty stats" $ \(stats, report) -> do
       Just _ <- newStatTiming stats "holes" 1
       rs <- replicateM 8 report
       let rs' =
@@ -99,7 +99,7 @@
                 i `mod` 100 == 0
             ]
       rs `shouldMatchList` rs'
-    it "computes timing stats correctly" $ const $ do
+    it "computes stats" $ const $ do
       let ps = reverse [5 .. 800] ++ [801 .. 1500]
           p90 = take (length ps * 90 `div` 100) (sort ps)
           p95 = take (length ps * 95 `div` 100) (sort ps)
@@ -138,7 +138,7 @@
       last t95.cumsquares `shouldBe` sumsq p95
       last t95.cumsums `shouldBe` sum p95
       median t95 `shouldBe` median' p95
-    it "reports timing stats" $ \(stats, report) -> do
+    it "reports stats" $ \(stats, report) -> do
       let timings = [5 .. 1500]
       Just t <- newStatTiming stats "kittens" 0
       forM_ timings (addTiming t)
@@ -184,38 +184,52 @@
         rs <- replicateM (length rs') report
         rs `shouldMatchList` rs'
   describe "gauge" $ do
-    it "reports gauge set events" $ \(stats, report) -> do
+    it "reports set events" $ \(stats, report) -> do
       let gauges = [51 .. 55]
-      Just g <- newStatGauge stats "speed" 1 50
+      Just g <- newStatGauge stats "speed" 50
       forM_ gauges (setGauge g)
       rs <- replicateM (length gauges) report
-      let rs' = map (\n -> Report "speed" (Gauge n) 1.0) gauges
+      let rs' = map (\n -> Report "speed" (Gauge n False) 1.0) gauges
       rs `shouldMatchList` rs'
-    it "reports gauge stats" $ \(stats, report) -> do
+    it "reports stats" $ \(stats, report) -> do
       let gauges = [51 .. 55]
-      Just g <- newStatGauge stats "speed" 1 50
+      Just g <- newStatGauge stats "radius" 50
       r <- report
-      r `shouldBe` Report "stats.gauges.speed" (Gauge 50) 1.0
+      r `shouldBe` Report "stats.gauges.radius" (Gauge 50 False) 1.0
       forM_ gauges (setGauge g)
       replicateM_ (length gauges) report
       rs <- replicateM 2 report
-      let rs' = replicate 2 $ Report "stats.gauges.speed" (Gauge 55) 1.0
+      let rs' = replicate 2 $ Report "stats.gauges.radius" (Gauge 55 False) 1.0
       rs `shouldMatchList` rs'
+    it "increments and decrements value" $ \(stats, report) -> do
+      Just g <- newStatGauge stats "breadth" 50
+      incrementGauge g 5
+      report `shouldReturn` Report "breadth" (Gauge 5 True) 1.0
+      report `shouldReturn` Report "stats.gauges.breadth" (Gauge 55 False) 1.0
+      incrementGauge g (-10)
+      report `shouldReturn` Report "breadth" (Gauge (-10) True) 1.0
+      report `shouldReturn` Report "stats.gauges.breadth" (Gauge 45 False) 1.0
+      decrementGauge g 50
+      report `shouldReturn` Report "breadth" (Gauge (-50) True) 1.0
+      report `shouldReturn` Report "stats.gauges.breadth" (Gauge 0 False) 1.0
+      decrementGauge g (-25)
+      report `shouldReturn` Report "breadth" (Gauge 25 True) 1.0
+      report `shouldReturn` Report "stats.gauges.breadth" (Gauge 25 False) 1.0
   describe "set" $ do
-    it "reports set events" $ \(stats, report) -> do
+    it "reports events" $ \(stats, report) -> do
       let set = ["one", "two", "three", "three"]
-      Just s <- newStatSet stats "numbers"
+      Just s <- newStatSet stats "potatoes"
       forM_ set (newSetElement s)
       rs <- replicateM (length set) report
-      let rs' = map (\x -> Report "numbers" (Set x) 1.0) set
+      let rs' = map (\x -> Report "potatoes" (Set x) 1.0) set
       rs `shouldMatchList` rs'
-    it "reports set stats" $ \(stats, report) -> do
+    it "reports stats" $ \(stats, report) -> do
       let set = ["two", "three", "one", "two", "three", "three"]
-      Just s <- newStatSet stats "numbers"
+      Just s <- newStatSet stats "bananas"
       forM_ set (newSetElement s)
       let rs' =
-            [ Report "stats.sets.numbers.count" (Counter 3) 1.0,
-              Report "stats.sets.numbers.count" (Counter 0) 1.0
+            [ Report "stats.sets.bananas.count" (Counter 3) 1.0,
+              Report "stats.sets.bananas.count" (Counter 0) 1.0
             ]
       rs <- replicateM (length set + length rs') report
       rs `shouldEndWith` rs'
@@ -238,7 +252,7 @@
   where
     fwd s2 q = forever $ do
       bs <- liftIO $ B.lines <$> recv s2 (2 ^ (20 :: Int))
-      let rs = mapMaybe parseReport bs
+      let rs = map (fromJust . parseReport) bs
       mapM_ (atomically . writeTQueue q) rs
 
 withMockSockets :: (MonadUnliftIO m) => ((Socket, Socket) -> m a) -> m a
