diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,18 @@
 The format is based on [Keep a Changelog][chg] and this project adheres to
 [Haskell's Package Versioning Policy][pvp]
 
+## `0.4.10` - 2022-03-22
+
+  - Add `AWS.Lambda.Events.EventBridge.EventBridgeEvent` type for
+    subscribing Lambda functions to AWS EventBridge Events
+  - Add `AWS.Lambda.Events.EventBridge.SSM.ParameterStoreChange` type
+    for parsing AWS Systems Manager Parameter Store Change events
+    delivered via AWS EventBridge.
+  - When the runtime encounters an error, write it out to the Cloudwatch logs
+    (via stderr), and do so in a format that can be guaranteed and later
+    extended.
+  - Eliminate redundant import compiler warnings
+
 ## `0.4.9` - 2022-02-28
 
   - Add `KafkaEvent` type for subscribing Lambda functions to Kafka
diff --git a/hal.cabal b/hal.cabal
--- a/hal.cabal
+++ b/hal.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
+-- This file has been generated from package.yaml by hpack version 0.34.5.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 804d66701a670f6c063313f96b6b5c9754cf0a4a67b7fc4651e11ed8ab059608
+-- hash: 7e0538a9f4a9a866214c8f9649acec329a1eb823391fd64f645a21b85459f566
 
 name:           hal
-version:        0.4.9
+version:        0.4.10
 synopsis:       A runtime environment for Haskell applications running on AWS Lambda.
 description:    This library uniquely supports different types of AWS Lambda Handlers for your
                 needs/comfort with advanced Haskell. Instead of exposing a single function
@@ -35,6 +35,8 @@
       AWS.Lambda.Context
       AWS.Lambda.Events.ApiGateway.ProxyRequest
       AWS.Lambda.Events.ApiGateway.ProxyResponse
+      AWS.Lambda.Events.EventBridge
+      AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange
       AWS.Lambda.Events.Kafka
       AWS.Lambda.Events.S3
       AWS.Lambda.Events.SQS
@@ -98,6 +100,9 @@
       AWS.Lambda.Events.ApiGateway.ProxyRequest.Spec
       AWS.Lambda.Events.ApiGateway.ProxyResponse.Gen
       AWS.Lambda.Events.ApiGateway.ProxyResponse.Spec
+      AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange.Gen
+      AWS.Lambda.Events.EventBridge.Gen
+      AWS.Lambda.Events.EventBridge.Spec
       AWS.Lambda.Events.Kafka.Gen
       AWS.Lambda.Events.Kafka.Spec
       Gen.Header
diff --git a/src/AWS/Lambda/Events/ApiGateway/ProxyResponse.hs b/src/AWS/Lambda/Events/ApiGateway/ProxyResponse.hs
--- a/src/AWS/Lambda/Events/ApiGateway/ProxyResponse.hs
+++ b/src/AWS/Lambda/Events/ApiGateway/ProxyResponse.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-|
 Module      : AWS.Lambda.Events.ApiGateway.ProxyResponse
 Description : Data types that represent typical lambda responses
@@ -35,7 +36,9 @@
 import           Data.Hashable             (Hashable)
 import           Data.HashMap.Strict       (HashMap)
 import qualified Data.HashMap.Strict       as H
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup            ((<>))
+#endif
 import qualified Data.Text                 as T
 import qualified Data.Text.Encoding        as TE
 import qualified Data.Text.Lazy            as TL
diff --git a/src/AWS/Lambda/Events/EventBridge.hs b/src/AWS/Lambda/Events/EventBridge.hs
new file mode 100644
--- /dev/null
+++ b/src/AWS/Lambda/Events/EventBridge.hs
@@ -0,0 +1,146 @@
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE DeriveTraversable #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+{-|
+Module      : AWS.Lambda.Events.EventBridge
+Description : Data types for consuming EventBridge events.
+License     : BSD3
+Stability   : stable
+
+Data types for Lambda functions which subscribe to AWS EventBridge
+events.
+
+-}
+
+module AWS.Lambda.Events.EventBridge (
+  EventBridgeEvent,
+  EventBridgeEvent'(..)
+) where
+
+import Control.Monad  (unless)
+import Data.Aeson
+import Data.Text      (Text)
+import Data.Time      (UTCTime)
+import GHC.Generics   (Generic)
+import Prelude        hiding (id)
+
+-- | Convenience alias for events of unknown type. Most of the time
+-- you will want to define or use a data type @Foo@ representing the
+-- @detail@ payload, and write an @instance FromJSON Foo@ to get
+-- @instance FromJSON ('EventBridgeEvent'' Foo)@. See the
+-- @AWS.Lambda.Events.EventBridge.Detail.*@ modules for data types
+-- which you can use.
+type EventBridgeEvent = EventBridgeEvent' Value
+
+-- | Represents an event from Amazon EventBridge.
+--
+-- See the <https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html AWS documentation>
+-- for information about events, and a sample payload.
+data EventBridgeEvent' a = EventBridgeEvent {
+  -- | By default, this is set to 0 (zero) in all events.
+  version :: Text,
+
+  -- | A Version 4 UUID that's generated for every event. You can use
+  -- id to trace events as they move through rules to targets.
+  id :: Text,
+
+  -- | Identifies, in combination with the source field, the fields
+  -- and values that appear in the detail field.
+  --
+  -- Events that are delivered by CloudTrail have AWS API Call via
+  -- CloudTrail as the value for detail-type.
+  --
+  -- __NOTE:__ This is called @detail-type@ in the AWS payload.
+  detailType :: Text,
+
+  -- | Identifies the service that generated the event. All events
+  -- that come from AWS services begin with "aws." Customer-generated
+  -- events can have any value here, as long as it doesn't begin with
+  -- "aws." We recommend the use of Java package-name style reverse
+  -- domain-name strings.
+  --
+  -- To find the correct value for source for an AWS service, see The
+  -- condition keys table, select a service from the list, and look
+  -- for the service prefix. For example, the source value for Amazon
+  -- CloudFront is aws.cloudfront.
+  source :: Text,
+
+  -- | The 12-digit number identifying an AWS account.
+  account :: Text,
+
+  -- | The event timestamp, which can be specified by the service
+  -- originating the event. If the event spans a time interval, the
+  -- service can report the start time, so this value might be before
+  -- the time the event is received.
+  time :: UTCTime,
+
+  -- | Identifies the AWS Region where the event originated.
+  region :: Text,
+
+  -- | A JSON array that contains ARNs that identify resources that
+  -- are involved in the event. The service generating the event
+  -- determines whether to include these ARNs. For example, Amazon EC2
+  -- instance state-changes include Amazon EC2 instance ARNs, Auto
+  -- Scaling events include ARNs for both instances and Auto Scaling
+  -- groups, but API calls with AWS CloudTrail do not include resource
+  -- ARNs.
+  resources :: [Text],
+
+  -- | A JSON object that contains information about the event. The
+  -- service generating the event determines the content of this
+  -- field. The detail content can be as simple as two fields. AWS API
+  -- call events have detail objects with approximately 50 fields
+  -- nested several levels deep.
+  detail :: a
+} deriving (Eq, Show, Generic, Functor, Foldable, Traversable)
+
+instance FromJSON a => FromJSON (EventBridgeEvent' a) where
+  parseJSON = withObject "EventBridgeEvent" $ \o -> do
+    version <- o .: "version"
+    unless (version == "0") $ fail "version != 0"
+    id <- o .: "id"
+    detailType <- o .: "detail-type"
+    source <- o .: "source"
+    account <- o .: "account"
+    time <- o .: "time"
+    region <- o .: "region"
+    resources <- o .: "resources"
+    detail <- o .: "detail"
+
+    pure EventBridgeEvent
+      { version
+      , id
+      , detailType
+      , source
+      , account
+      , time
+      , region
+      , resources
+      , detail
+      }
+
+instance ToJSON a => ToJSON (EventBridgeEvent' a) where
+  toJSON event = object
+    [ "version" .= version event
+    , "id" .= id event
+    , "detail-type" .= detailType event
+    , "source" .= source event
+    , "account" .= account event
+    , "time" .= time event
+    , "region" .= region event
+    , "resources" .= resources event
+    , "detail" .= detail event
+    ]
+
+  toEncoding event = pairs $ mconcat
+    [ "version" .= version event
+    , "id" .= id event
+    , "detail-type" .= detailType event
+    , "source" .= source event
+    , "account" .= account event
+    , "time" .= time event
+    , "region" .= region event
+    , "resources" .= resources event
+    , "detail" .= detail event
+    ]
diff --git a/src/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange.hs b/src/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange.hs
new file mode 100644
--- /dev/null
+++ b/src/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange.hs
@@ -0,0 +1,134 @@
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+-- |
+-- Module      : AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange
+-- Description : Data types for AWS Systems Manager Parameter Store Change events.
+-- License     : BSD3
+-- Stability   : stable
+module AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange
+  ( ParameterStoreChange (..),
+    Operation (.., Create, Update, Delete, LabelParameterVersion),
+    Type (..),
+  )
+where
+
+import Data.Aeson
+  ( FromJSON (..),
+    ToJSON (..),
+    object,
+    pairs,
+    withObject,
+    withText,
+    (.:),
+    (.:?),
+    (.=),
+  )
+import qualified Data.Aeson as Aeson
+import Data.Aeson.Encoding (text)
+import Data.Text (Text)
+import GHC.Generics (Generic)
+
+-- | A @Parameter Store Change@ event from Amazon EventBridge. This
+-- structure corresponds to the contents of the @"detail"@ field of an
+-- EventBridge event, so a full payload from EventBridge can be parsed
+-- into a @'AWS.Lambda.Events.EventBridge'' ParameterStoreChange@.
+--
+-- Sample event payloads are provided in the
+-- <https://docs.aws.amazon.com/systems-manager/latest/userguide/monitoring-systems-manager-event-examples.html#SSM-Parameter-Store-event-types AWS Systems Manager User Guide>.
+data ParameterStoreChange = ParameterStoreChange
+  { operation :: Operation,
+    name :: Text,
+    type_ :: Type,
+    description :: Maybe Text
+  }
+  deriving (Eq, Show, Generic)
+
+instance FromJSON ParameterStoreChange where
+  parseJSON = withObject "ParameterStoreChange" $ \o -> do
+    operation <- o .: "operation"
+    name <- o .: "name"
+    type_ <- o .: "type"
+    description <- o .:? "description"
+
+    pure
+      ParameterStoreChange
+        { operation,
+          name,
+          type_,
+          description
+        }
+
+instance ToJSON ParameterStoreChange where
+  toJSON change =
+    object
+      [ "operation" .= operation change,
+        "name" .= name change,
+        "type" .= type_ change,
+        "description" .= description change
+      ]
+
+  toEncoding change =
+    pairs $
+      mconcat
+        [ "operation" .= operation change,
+          "name" .= name change,
+          "type" .= type_ change,
+          "description" .= description change
+        ]
+
+-- | AWS provides no schema for the @"operation"@ field, so we provide
+-- a newtype wrapper and pattern synonyms which we think are complete,
+-- based on AWS documentation.
+newtype Operation = Operation Text deriving (Eq, Show, Generic)
+
+pattern Create :: Operation
+pattern Create = Operation "Create"
+
+pattern Update :: Operation
+pattern Update = Operation "Update"
+
+pattern Delete :: Operation
+pattern Delete = Operation "Delete"
+
+pattern LabelParameterVersion :: Operation
+pattern LabelParameterVersion = Operation "LabelParameterVersion"
+
+{-# COMPLETE Create, Update, Delete, LabelParameterVersion #-}
+
+instance FromJSON Operation where
+  parseJSON = withText "Operation" $ \case
+    "Create" -> pure Create
+    "Update" -> pure Update
+    "Delete" -> pure Delete
+    "LabelParameterVersion" -> pure LabelParameterVersion
+    t -> fail $ "Unrecognized operation: " ++ show t
+
+instance ToJSON Operation where
+  toJSON (Operation op) = Aeson.String op
+  toEncoding (Operation op) = text op
+
+-- | AWS provides no schema for the @"type"@ field, but these are the
+-- only three types of parameters you can create in Parameter Store.
+data Type = String | StringList | SecureString
+  deriving (Eq, Ord, Show, Enum, Bounded, Generic)
+
+instance FromJSON Type where
+  parseJSON = withText "Type" $ \case
+    "String" -> pure String
+    "StringList" -> pure StringList
+    "SecureString" -> pure SecureString
+    t -> fail $ "Unrecognised type: " ++ show t
+
+instance ToJSON Type where
+  toJSON =
+    Aeson.String . \case
+      String -> "String"
+      StringList -> "StringList"
+      SecureString -> "SecureString"
+
+  toEncoding =
+    text . \case
+      String -> "String"
+      StringList -> "StringList"
+      SecureString -> "SecureString"
diff --git a/src/AWS/Lambda/Events/Kafka.hs b/src/AWS/Lambda/Events/Kafka.hs
--- a/src/AWS/Lambda/Events/Kafka.hs
+++ b/src/AWS/Lambda/Events/Kafka.hs
@@ -53,7 +53,9 @@
 import           Data.Map               (Map)
 import           Data.Maybe             (catMaybes, maybeToList)
 import           Data.Scientific        (toBoundedInteger)
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup         ((<>))
+#endif
 import           Data.Text              (Text)
 import qualified Data.Text              as T
 import qualified Data.Text.Encoding     as TE
diff --git a/src/AWS/Lambda/RuntimeClient.hs b/src/AWS/Lambda/RuntimeClient.hs
--- a/src/AWS/Lambda/RuntimeClient.hs
+++ b/src/AWS/Lambda/RuntimeClient.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-|
 Module      : AWS.Lambda.RuntimeClient
 Description : HTTP related machinery for talking to the AWS Lambda Custom Runtime interface.
@@ -19,11 +20,10 @@
 import           AWS.Lambda.Context                (LambdaContext)
 import           AWS.Lambda.Internal               (StaticContext, getStaticContext)
 import           AWS.Lambda.RuntimeClient.Internal (eventResponseToNextData)
-import           Control.Applicative               ((<*>))
 import           Control.Concurrent                (threadDelay)
 import           Control.Exception                 (IOException, displayException,
                                                     throw, try)
-import           Control.Monad                     (unless)
+import           Control.Monad                     (unless, void)
 import           Control.Monad.IO.Class            (MonadIO, liftIO)
 import           Data.Aeson                        (Value, encode)
 import           Data.Aeson.Parser                 (value')
@@ -34,7 +34,9 @@
 import           Data.Conduit                      (ConduitM, runConduit, yield,
                                                     (.|))
 import           Data.Conduit.Attoparsec           (sinkParser)
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup                    ((<>))
+#endif
 import           GHC.Generics                      (Generic (..))
 import           Network.HTTP.Client               (BodyReader, HttpException,
                                                     Manager, Request,
@@ -59,6 +61,7 @@
                                                     status413,
                                                     statusIsSuccessful)
 import           System.Environment                (getEnv)
+import           System.IO                         (hPutStrLn, stderr)
 
 -- | Lambda runtime error that we pass back to AWS
 data LambdaError = LambdaError
@@ -153,8 +156,10 @@
     Right () -> return ()
 
 sendEventError :: RuntimeClientConfig -> BS.ByteString -> String -> IO ()
-sendEventError (RuntimeClientConfig baseRuntimeRequest manager _) reqId e =
-  fmap (const ()) $ runtimeClientRetry $ flip httpNoBody manager $ toEventErrorRequest reqId e baseRuntimeRequest
+sendEventError (RuntimeClientConfig baseRuntimeRequest manager _) reqId e = do
+  logErrorMsg e
+  let request = httpNoBody (toEventErrorRequest reqId e baseRuntimeRequest) manager
+  void $ runtimeClientRetry request
 
 sendInitError :: Request -> Manager -> String -> IO ()
 sendInitError baseRuntimeRequest manager e =
@@ -260,3 +265,13 @@
 
 setRequestPath :: BS.ByteString -> Request -> Request
 setRequestPath p req = req { path = p }
+
+-- Log Helpers
+
+-- TODO: This logging more-or-less looks like other runtimes, but there doesn't
+-- seem to be any specific standard or recommendations around this, and it
+-- varies across runtimes.  In the future, it may make sense to enable user
+-- specific formatting (similar to the Rust runtime).  But for now, not sure
+-- we'll ever see such an ask.
+logErrorMsg :: String -> IO ()
+logErrorMsg = hPutStrLn stderr . (<>) "ERROR Message: " . show
diff --git a/src/AWS/Lambda/RuntimeClient/Internal.hs b/src/AWS/Lambda/RuntimeClient/Internal.hs
--- a/src/AWS/Lambda/RuntimeClient/Internal.hs
+++ b/src/AWS/Lambda/RuntimeClient/Internal.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-|
 Module      : AWS.Lambda.RuntimeClient.Internal
 Description : Internal HTTP related machinery for talking to the AWS Lambda Custom Runtime interface.
@@ -22,7 +23,9 @@
 import qualified Data.ByteString.Internal as BSI
 import qualified Data.ByteString.Lazy     as BSW
 import           Data.CaseInsensitive     (original)
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup           ((<>))
+#endif
 import           Data.Text.Encoding       (decodeUtf8)
 import           Data.Time.Clock.POSIX    (posixSecondsToUTCTime)
 import           Network.HTTP.Client      (Response, responseBody,
diff --git a/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Parameters.hs b/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Parameters.hs
--- a/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Parameters.hs
+++ b/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Parameters.hs
@@ -1,9 +1,12 @@
+{-# LANGUAGE CPP #-}
 module AWS.Lambda.Events.ApiGateway.ProxyRequest.Gen.Parameters where
 
 import           Control.Monad.Trans.State
 import           Data.HashMap.Strict       (HashMap)
 import qualified Data.HashMap.Strict       as H
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup            ((<>))
+#endif
 import           Data.Set                  (Set)
 import qualified Data.Set                  as S
 import           Data.Text                 (Text)
diff --git a/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Resource.hs b/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Resource.hs
--- a/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Resource.hs
+++ b/test/AWS/Lambda/Events/ApiGateway/ProxyRequest/Gen/Resource.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE CPP #-}
 
 module AWS.Lambda.Events.ApiGateway.ProxyRequest.Gen.Resource where
 
@@ -9,7 +10,9 @@
 import qualified Data.HashMap.Strict       as H
 import           Data.List.NonEmpty        (NonEmpty)
 import qualified Data.List.NonEmpty        as NE
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup            ((<>))
+#endif
 import qualified Data.Set                  as S
 import           Data.Text                 (Text)
 import qualified Data.Text                 as T
diff --git a/test/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange/Gen.hs b/test/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange/Gen.hs
new file mode 100644
--- /dev/null
+++ b/test/AWS/Lambda/Events/EventBridge/Detail/SSM/ParameterStoreChange/Gen.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+module AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange.Gen where
+
+import           AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange (Operation(..), ParameterStoreChange(..))
+import           Hedgehog       (Gen)
+import qualified Hedgehog.Gen   as Gen
+import qualified Hedgehog.Range as Range
+import           Prelude        hiding (id)
+
+parameterStoreChange :: Gen ParameterStoreChange
+parameterStoreChange = do
+  operation <- Gen.element [Create, Update, Delete, LabelParameterVersion]
+  name <- Gen.text (Range.linear 1 200) Gen.unicode
+  type_ <- Gen.enumBounded
+  description <- Gen.maybe $ Gen.text (Range.linear 1 200) Gen.unicode
+
+  pure ParameterStoreChange
+    { operation
+    , name
+    , type_
+    , description
+    }
diff --git a/test/AWS/Lambda/Events/EventBridge/Gen.hs b/test/AWS/Lambda/Events/EventBridge/Gen.hs
new file mode 100644
--- /dev/null
+++ b/test/AWS/Lambda/Events/EventBridge/Gen.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE NamedFieldPuns #-}
+
+module AWS.Lambda.Events.EventBridge.Gen where
+
+import           AWS.Lambda.Events.EventBridge (EventBridgeEvent'(..),
+                                                EventBridgeEvent)
+import           Data.List                     (intersperse)
+import           Data.Text                     (Text)
+import qualified Data.Text                     as T
+import           Data.Time                     (UTCTime)
+import           Data.Time.Clock.POSIX         (posixSecondsToUTCTime)
+import           Data.Traversable              (for)
+import           Hedgehog                      (Gen)
+import qualified Hedgehog.Gen                  as Gen
+import qualified Hedgehog.Range                as Range
+import           Prelude                       hiding (id)
+
+eventBridgeEvent :: Gen EventBridgeEvent
+eventBridgeEvent = do
+  let version = "0"
+  id <- uuid
+  detailType <- Gen.text (Range.linear 1 200) Gen.unicode
+  source <- Gen.text (Range.linear 1 200) Gen.unicode
+  account <- awsAccount
+  time <- utcTime
+  region <- awsRegion
+  resources <- Gen.list (Range.linear 1 5) resource
+  let detail = "{}"
+
+  pure EventBridgeEvent
+    { version
+    , id
+    , detailType
+    , source
+    , account
+    , time
+    , region
+    , resources
+    , detail
+    }
+
+uuid :: Gen Text
+uuid = do
+  uuidParts <- for [ 7, 4, 4, 4, 12, 2 ] $ \n ->
+    Gen.text (Range.singleton n) Gen.hexit
+  pure $ T.intercalate "-" uuidParts
+
+utcTime :: Gen UTCTime
+utcTime = do
+  int <- Gen.int64
+    (Range.exponentialFrom 1600000000000 1650000000000 1700000000000)
+  let (seconds, millis) = int `divMod` 1000
+      posixSeconds = fromIntegral seconds + fromIntegral millis / 1000
+  pure $ posixSecondsToUTCTime posixSeconds
+
+awsAccount :: Gen Text
+awsAccount = Gen.text (Range.singleton 12) Gen.digit
+
+awsRegion :: Gen Text
+awsRegion = Gen.element ["ap-south-1", "us-east-2", "eu-west-3"]
+
+resource :: Gen Text
+resource = do
+  acc <- awsAccount
+  svc <- Gen.text (Range.linear 1 10) Gen.lower
+  reg <- awsRegion
+  res <- Gen.text (Range.linear 1 20) Gen.alphaNum
+  pure $ T.intercalate ":" ["arn:aws", svc, reg, acc, res]
diff --git a/test/AWS/Lambda/Events/EventBridge/Spec.hs b/test/AWS/Lambda/Events/EventBridge/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/AWS/Lambda/Events/EventBridge/Spec.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE QuasiQuotes #-}
+
+module AWS.Lambda.Events.EventBridge.Spec where
+
+import           Prelude                                                    hiding (id)
+
+import           AWS.Lambda.Events.EventBridge
+import qualified AWS.Lambda.Events.EventBridge.Gen                          as EventBridge
+import qualified AWS.Lambda.Events.EventBridge.Detail.SSM.ParameterStoreChange.Gen as ParameterStoreChange
+import           Data.Aeson                                                 (decode, eitherDecode, encode,
+                                                                             object, (.=), Value(..))
+import           Data.ByteString.Lazy                                       (ByteString)
+import           Data.Time                                                  (UTCTime(..), fromGregorian,
+                                                                             secondsToDiffTime)
+import           Hedgehog                                                   (forAll, tripping)
+import           Test.Hspec                                                 (Spec, describe, shouldBe, specify)
+import           Test.Hspec.Hedgehog                                        (hedgehog)
+import           Test.Hspec.Runner                                          (hspec)
+import           Text.RawString.QQ                                          (r)
+
+spec :: Spec
+spec = do
+  describe "EventBridge" $ do
+    specify "read sample payload" $
+      eitherDecode samplePayload `shouldBe` Right expectedPayload
+
+    describe "properties" $ do
+      specify "EventBridgeEvent tripping" $
+        hedgehog $ do
+          payload <- forAll EventBridge.eventBridgeEvent
+          tripping payload encode decode
+
+    describe "SSM" $
+      specify "ParameterStoreChange tripping" $
+        hedgehog $ do
+          change <- forAll ParameterStoreChange.parameterStoreChange
+          tripping change encode decode
+
+samplePayload :: ByteString
+samplePayload = [r|
+{
+   "version":"0",
+   "id":"01234567-0123-0123-0123-0123456789ab",
+   "detail-type":"Maintenance Window Target Registration Notification",
+   "source":"aws.ssm",
+   "account":"123456789012",
+   "time":"2016-11-16T00:58:37Z",
+   "region":"us-east-2",
+   "resources":[
+      "arn:aws:ssm:us-east-2:123456789012:maintenancewindow/mw-0ed7251d3fcf6e0c2",
+      "arn:aws:ssm:us-east-2:123456789012:windowtarget/e7265f13-3cc5-4f2f-97a9-7d3ca86c32a6"
+   ],
+   "detail":{
+      "window-target-id":"e7265f13-3cc5-4f2f-97a9-7d3ca86c32a6",
+      "window-id":"mw-0ed7251d3fcf6e0c2",
+      "status":"REGISTERED"
+   }
+}
+|]
+
+expectedPayload :: EventBridgeEvent
+expectedPayload = EventBridgeEvent
+  { version = "0"
+  , id = "01234567-0123-0123-0123-0123456789ab"
+  , detailType = "Maintenance Window Target Registration Notification"
+  , source = "aws.ssm"
+  , account = "123456789012"
+  , time = UTCTime (fromGregorian 2016 11 16) (secondsToDiffTime $ 58 * 60 + 37)
+  , region = "us-east-2"
+  , resources =
+    [ "arn:aws:ssm:us-east-2:123456789012:maintenancewindow/mw-0ed7251d3fcf6e0c2"
+    , "arn:aws:ssm:us-east-2:123456789012:windowtarget/e7265f13-3cc5-4f2f-97a9-7d3ca86c32a6"
+    ]
+  , detail = object
+    [ "window-target-id" .= String "e7265f13-3cc5-4f2f-97a9-7d3ca86c32a6"
+    , "window-id" .= String "mw-0ed7251d3fcf6e0c2"
+    , "status" .= String "REGISTERED"
+    ]
+  }
diff --git a/test/AWS/Lambda/Events/Kafka/Gen.hs b/test/AWS/Lambda/Events/Kafka/Gen.hs
--- a/test/AWS/Lambda/Events/Kafka/Gen.hs
+++ b/test/AWS/Lambda/Events/Kafka/Gen.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 module AWS.Lambda.Events.Kafka.Gen where
 
 import AWS.Lambda.Events.Kafka              (KafkaEvent(KafkaEvent),
@@ -14,7 +15,9 @@
 import qualified Data.List.NonEmpty         as NE
 import           Data.List.NonEmpty         (NonEmpty)
 import           Data.Map                   (Map)
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup             ((<>))
+#endif
 import           Data.Text                  (Text)
 import qualified Data.Text                  as T
 import           Data.Time                  (UTCTime)
diff --git a/test/Gen/Header.hs b/test/Gen/Header.hs
--- a/test/Gen/Header.hs
+++ b/test/Gen/Header.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 module Gen.Header where
 
 import           Control.Monad.Trans.State
@@ -6,7 +7,9 @@
 import           Data.Char                 (toUpper, toLower)
 import           Data.HashMap.Strict       (HashMap)
 import qualified Data.HashMap.Strict       as H
+#if !MIN_VERSION_base(4,11,0)
 import           Data.Semigroup            ((<>))
+#endif
 import           Data.Set                  (Set)
 import qualified Data.Set                  as S
 import           Data.Text                 (Text)
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,28 +1,32 @@
-import           AWS.Lambda.Context                (ClientApplication (..),
-                                                    ClientContext (..),
-                                                    CognitoIdentity (..),
-                                                    LambdaContext (..))
-import qualified Gen.Header                        as Header
+{-# LANGUAGE CPP #-}
+import           AWS.Lambda.Context                 (ClientApplication (..),
+                                                     ClientContext (..),
+                                                     CognitoIdentity (..),
+                                                     LambdaContext (..))
+import qualified Gen.Header                         as Header
 import qualified AWS.Lambda.Events.ApiGateway.ProxyRequest.Spec as ProxyRequest
 import qualified AWS.Lambda.Events.ApiGateway.ProxyResponse.Spec as ProxyResponse
 
-import qualified AWS.Lambda.Events.Kafka.Spec      as Kafka
-import           AWS.Lambda.Internal               (StaticContext (..))
-import           AWS.Lambda.RuntimeClient.Internal (eventResponseToNextData)
-import           Data.Aeson                        (Value (Null))
-import qualified Data.CaseInsensitive              as CI
-import           Data.Map                          (singleton)
-import           Data.Semigroup                    ((<>))
-import           Data.Time.Clock.POSIX             (posixSecondsToUTCTime)
+import qualified AWS.Lambda.Events.EventBridge.Spec as EventBridge
+import qualified AWS.Lambda.Events.Kafka.Spec       as Kafka
+import           AWS.Lambda.Internal                (StaticContext (..))
+import           AWS.Lambda.RuntimeClient.Internal  (eventResponseToNextData)
+import           Data.Aeson                         (Value (Null))
+import qualified Data.CaseInsensitive               as CI
+import           Data.Map                           (singleton)
+#if !MIN_VERSION_base(4,11,0)
+import           Data.Semigroup                     ((<>))
+#endif
+import           Data.Time.Clock.POSIX              (posixSecondsToUTCTime)
 import           Hedgehog
-import qualified Hedgehog.Gen                      as Gen
-import qualified Hedgehog.Range                    as Range
-import           Network.HTTP.Client.Internal      (Response (..))
-import           Network.HTTP.Types                (Header)
-import           Test.Hspec                        (describe, it, shouldBe,
-                                                    shouldStartWith, specify)
-import           Test.Hspec.Hedgehog               (hedgehog)
-import           Test.Hspec.Runner                 (hspec)
+import qualified Hedgehog.Gen                       as Gen
+import qualified Hedgehog.Range                     as Range
+import           Network.HTTP.Client.Internal       (Response (..))
+import           Network.HTTP.Types                 (Header)
+import           Test.Hspec                         (describe, it, shouldBe,
+                                                     shouldStartWith, specify)
+import           Test.Hspec.Hedgehog                (hedgehog)
+import           Test.Hspec.Runner                  (hspec)
 
 main :: IO ()
 main =
@@ -31,6 +35,7 @@
       describe "ApiGateway" $ do
         describe "ProxyRequest" ProxyRequest.spec
         describe "ProxyResponse" ProxyResponse.spec
+      describe "EventBridge" EventBridge.spec
       describe "Kafka" Kafka.spec
 
     describe "Event Response Data" $ do
