diff --git a/AWS/Class.hs b/AWS/Class.hs
--- a/AWS/Class.hs
+++ b/AWS/Class.hs
@@ -49,13 +49,19 @@
 
 data AWSException
     = ClientError
-        { errorAction :: ByteString
-        , errorStatus :: Int
-        , errorCode :: Text
-        , errorMessage :: Maybe Text
-        , errorRequestId :: Text
+        { clientErrorAction :: ByteString
+        , clientErrorStatus :: Int
+        , clientErrorCode :: Text
+        , clientErrorMessage :: Maybe Text
+        , clientErrorRequestId :: Text
         } -- ^ This error is caused by client requests.
-    | ServerError -- ^ XXX: Not implimented. Internal error of AWS.
+    | ServerError
+        { serverErrorAction :: ByteString
+        , serverErrorStatus :: Int
+        , serverErrorCode :: Text
+        , serverErrorMessage :: Maybe Text
+        , serverErrorRequestId :: Text
+        } -- ^ This error is caused by server error in AWS.
     | ResponseParseError Text
     | FromTextError Text
         -- ^ parse error: cannot convert Text to oher data type.
diff --git a/AWS/CloudWatch/Alarm.hs b/AWS/CloudWatch/Alarm.hs
--- a/AWS/CloudWatch/Alarm.hs
+++ b/AWS/CloudWatch/Alarm.hs
@@ -50,7 +50,7 @@
 stringifyStateValue StateValueAlarm = "ALARM"
 stringifyStateValue StateValueInsufficientData = "INSUFFICIENT_DATA"
 
-sinkMetricAlarm :: MonadThrow m => GLSink Event m MetricAlarm
+sinkMetricAlarm :: MonadThrow m => Consumer Event m MetricAlarm
 sinkMetricAlarm =
     MetricAlarm
     <$> getT "AlarmDescription"
@@ -154,7 +154,7 @@
 stringifyHistoryType HistoryTypeStateUpdate = "StateUpdate"
 stringifyHistoryType HistoryTypeAction = "Action"
 
-sinkAlarmHistory :: MonadThrow m => GLSink Event m AlarmHistory
+sinkAlarmHistory :: MonadThrow m => Consumer Event m AlarmHistory
 sinkAlarmHistory =
     AlarmHistory
     <$> getT "Timestamp"
@@ -180,7 +180,7 @@
 setAlarmState
     :: (MonadBaseControl IO m, MonadResource m)
     => Text -- ^ The name for the alarm.
-    -> Text -- ^ The reason that this alarm is set to this specific state (in human-readable text format) 
+    -> Text -- ^ The reason that this alarm is set to this specific state (in human-readable text format)
     -> Text -- ^ The reason that this alarm is set to this specific state (in machine-readable JSON format)
     -> StateValue -- ^ The value of the state.
     -> CloudWatch m ()
diff --git a/AWS/CloudWatch/Internal.hs b/AWS/CloudWatch/Internal.hs
--- a/AWS/CloudWatch/Internal.hs
+++ b/AWS/CloudWatch/Internal.hs
@@ -25,17 +25,17 @@
     :: (MonadBaseControl IO m, MonadResource m)
     => ByteString -- ^ Action
     -> [QueryParam]
-    -> GLSink Event m a
+    -> Consumer Event m a
     -> CloudWatch m a
 cloudWatchQuery = commonQuery apiVersion
 
 elements :: MonadThrow m
     => Text
-    -> GLSink Event m a
-    -> GLSink Event m [a]
+    -> Consumer Event m a
+    -> Consumer Event m [a]
 elements name f = element (name <> "s") $ listConsumer name f
 
-sinkDimension :: MonadThrow m => GLSink Event m Dimension
+sinkDimension :: MonadThrow m => Consumer Event m Dimension
 sinkDimension = Dimension <$> getT "Name" <*> getT "Value"
 
 fromDimension :: Dimension -> [QueryParam]
diff --git a/AWS/CloudWatch/Metric.hs b/AWS/CloudWatch/Metric.hs
--- a/AWS/CloudWatch/Metric.hs
+++ b/AWS/CloudWatch/Metric.hs
@@ -44,7 +44,7 @@
         , "NextToken" |=? nt
         ]
 
-sinkMetric :: MonadThrow m => GLSink Event m Metric
+sinkMetric :: MonadThrow m => Consumer Event m Metric
 sinkMetric =
     Metric
     <$> members "Dimensions" sinkDimension
diff --git a/AWS/EC2/Acl.hs b/AWS/EC2/Acl.hs
--- a/AWS/EC2/Acl.hs
+++ b/AWS/EC2/Acl.hs
@@ -36,7 +36,7 @@
         ]
 
 networkAclSink :: MonadThrow m
-    => GLSink Event m NetworkAcl
+    => Consumer Event m NetworkAcl
 networkAclSink = NetworkAcl
     <$> getT "networkAclId"
     <*> getT "vpcId"
diff --git a/AWS/EC2/Address.hs b/AWS/EC2/Address.hs
--- a/AWS/EC2/Address.hs
+++ b/AWS/EC2/Address.hs
@@ -39,7 +39,7 @@
         , filtersParam filters
         ]
 
-    addressSet :: MonadThrow m => GLConduit Event m Address
+    addressSet :: MonadThrow m => Conduit Event m Address
     addressSet = itemConduit "addressesSet" $ Address
         <$> getT "publicIp"
         <*> getT "allocationId"
@@ -120,4 +120,4 @@
     p (DisassociateAddressRequestEc2 pip)
         = ["PublicIp" |= toText pip]
     p (DisassociateAddressRequestVpc aid)
-        = ["AssociationId" |= toText aid]
+        = ["AssociationId" |= aid]
diff --git a/AWS/EC2/AvailabilityZone.hs b/AWS/EC2/AvailabilityZone.hs
--- a/AWS/EC2/AvailabilityZone.hs
+++ b/AWS/EC2/AvailabilityZone.hs
@@ -28,7 +28,7 @@
         , filtersParam filters
         ]
     availabilityZoneInfo :: MonadThrow m
-        => GLConduit Event m AvailabilityZone
+        => Conduit Event m AvailabilityZone
     availabilityZoneInfo = itemConduit "availabilityZoneInfo" $
         AvailabilityZone
         <$> getT "zoneName"
diff --git a/AWS/EC2/ConversionTask.hs b/AWS/EC2/ConversionTask.hs
--- a/AWS/EC2/ConversionTask.hs
+++ b/AWS/EC2/ConversionTask.hs
@@ -31,7 +31,7 @@
 
 conversionTaskSink
     :: MonadThrow m
-    => GLSink Event m ConversionTask
+    => Consumer Event m ConversionTask
 conversionTaskSink = ConversionTask
     <$> getT "conversionTaskId"
     <*> getT "expirationTime"
@@ -64,7 +64,7 @@
 
 diskImageDescriptionSink
     :: MonadThrow m
-    => GLSink Event m DiskImageDescription
+    => Consumer Event m DiskImageDescription
 diskImageDescriptionSink = DiskImageDescription
     <$> getT "format"
     <*> getT "size"
@@ -73,7 +73,7 @@
 
 diskImageVolumeDescriptionSink
     :: MonadThrow m
-    => GLSink Event m DiskImageVolumeDescription
+    => Consumer Event m DiskImageVolumeDescription
 diskImageVolumeDescriptionSink = DiskImageVolumeDescription
     <$> getT "size"
     <*> getT "id"
diff --git a/AWS/EC2/Image.hs b/AWS/EC2/Image.hs
--- a/AWS/EC2/Image.hs
+++ b/AWS/EC2/Image.hs
@@ -40,7 +40,7 @@
         ]
 
 imageItem :: MonadThrow m
-    => GLSink Event m Image
+    => Consumer Event m Image
 imageItem = Image
     <$> getT "imageId"
     <*> getT "imageLocation"
@@ -66,7 +66,7 @@
     <*> resourceTagSink
     <*> getT "hypervisor"
 
-blockDeviceMappingSink :: MonadThrow m => GLSink Event m [BlockDeviceMapping]
+blockDeviceMappingSink :: MonadThrow m => Consumer Event m [BlockDeviceMapping]
 blockDeviceMappingSink = itemsSet "blockDeviceMapping" (
     BlockDeviceMapping
     <$> getT "deviceName"
@@ -135,10 +135,7 @@
 describeImageAttribute iid attr =
     ec2Query "DescribeImageAttribute" params $ AMIAttributeDescription
         <$> getT "imageId"
-        <*> itemsSet "launchPermission"
-            (LaunchPermissionItem
-            <$> getT "group"
-            <*> getT "userId")
+        <*> itemsSet "launchPermission" launchPermissionItemSink
         <*> itemsSet "productCodes"
             (ProductCodeItem
             <$> getT "productCode")
@@ -158,10 +155,17 @@
     attrText AMIProductCodes       = "productCodes"
     attrText AMIBlockDeviceMapping = "blockDeviceMapping"
 
+launchPermissionItemSink :: MonadThrow m => Consumer Event m LaunchPermissionItem
+launchPermissionItemSink = do
+    mg <- elementM "group" text
+    case mg of
+        Just g -> return $ LaunchPermissionItemGroup g
+        Nothing -> LaunchPermissionItemUserId <$> getT "userId"
+
 modifyImageAttribute
     :: (MonadResource m, MonadBaseControl IO m)
     => Text -- ^ ImageId
-    -> LaunchPermission -- ^ LaunchPermission
+    -> Maybe LaunchPermission -- ^ LaunchPermission
     -> [Text] -- ^ ProductCode
     -> Maybe Text -- ^ Description
     -> EC2 m Bool
@@ -171,7 +175,7 @@
     params =
         [ "ImageId" |= iid
         , "ProductCode" |.#= pcs
-        , "LaunchPermission" |. launchPermissionParams lp
+        , "LaunchPermission" |.? launchPermissionParams <$> lp
         , "Description" |.+ "Value" |=? desc
         ]
 
@@ -181,7 +185,5 @@
     , "Remove" |.#. map itemParams (launchPermissionRemove lp)
     ]
   where
-    itemParams item =
-        [ "Group" |= launchPermissionItemGroup item
-        , "UserId" |= launchPermissionUserId item
-        ]
+    itemParams (LaunchPermissionItemGroup g) = ["Group" |= g]
+    itemParams (LaunchPermissionItemUserId u) = ["UserId" |= u]
diff --git a/AWS/EC2/Instance.hs b/AWS/EC2/Instance.hs
--- a/AWS/EC2/Instance.hs
+++ b/AWS/EC2/Instance.hs
@@ -52,7 +52,7 @@
         ]
 
 reservationSink :: MonadThrow m
-    => GLSink Event m Reservation
+    => Consumer Event m Reservation
 reservationSink =
     Reservation
     <$> getT "reservationId"
@@ -62,7 +62,7 @@
     <*> getT "requesterId"
 
 instanceSetSink :: MonadThrow m
-    => GLSink Event m [Instance]
+    => Consumer Event m [Instance]
 instanceSetSink = itemsSet "instancesSet" $
     Instance
     <$> getT "instanceId"
@@ -112,7 +112,7 @@
     <*> getT "ebsOptimized"
 
 instanceBlockDeviceMappingsSink :: MonadThrow m
-    => GLSink Event m [InstanceBlockDeviceMapping]
+    => Consumer Event m [InstanceBlockDeviceMapping]
 instanceBlockDeviceMappingsSink = itemsSet "blockDeviceMapping" (
     InstanceBlockDeviceMapping
     <$> getT "deviceName"
@@ -141,13 +141,13 @@
     (lookup code instanceStateCodes)
 
 instanceStateSink :: MonadThrow m
-    => Text -> GLSink Event m InstanceState
+    => Text -> Consumer Event m InstanceState
 instanceStateSink label = element label $ codeToState
     <$> getT "code"
     <*> getT "name"
 
 networkInterfaceSink :: MonadThrow m
-    => GLSink Event m [InstanceNetworkInterface]
+    => Consumer Event m [InstanceNetworkInterface]
 networkInterfaceSink = itemsSet "networkInterfaceSet" $
     InstanceNetworkInterface
     <$> getT "networkInterfaceId"
@@ -179,7 +179,7 @@
         )
 
 instanceNetworkInterfaceAssociationSink :: MonadThrow m
-    => GLSink Event m (Maybe InstanceNetworkInterfaceAssociation)
+    => Consumer Event m (Maybe InstanceNetworkInterfaceAssociation)
 instanceNetworkInterfaceAssociationSink = elementM "association" $
     InstanceNetworkInterfaceAssociation
     <$> getT "publicIp"
@@ -207,7 +207,7 @@
         ]
 
 instanceStatusSet :: MonadThrow m
-    => GLConduit Event m InstanceStatus
+    => Conduit Event m InstanceStatus
 instanceStatusSet = do
     itemConduit "instanceStatusSet" $
         InstanceStatus
@@ -225,7 +225,7 @@
         <*> instanceStatusTypeSink "instanceStatus"
 
 instanceStatusTypeSink :: MonadThrow m
-    => Text -> GLSink Event m InstanceStatusType
+    => Text -> Consumer Event m InstanceStatusType
 instanceStatusTypeSink name = element name $
     InstanceStatusType
     <$> getT "status"
@@ -521,12 +521,12 @@
 modifyInstanceAttribute
     :: (MonadResource m, MonadBaseControl IO m)
     => Text -- ^ InstanceId
-    -> [ModifyInstanceAttributeRequest]
+    -> ModifyInstanceAttributeRequest
     -> EC2 m Bool
-modifyInstanceAttribute iid attrs =
+modifyInstanceAttribute iid attr =
     ec2Query "ModifyInstanceAttribute" params $ getT "return"
   where
-    params = ("InstanceId" |= iid) : map miap attrs
+    params = ["InstanceId" |= iid, miap attr]
 
 miap :: ModifyInstanceAttributeRequest -> QueryParam
 miap (ModifyInstanceAttributeRequestInstanceType a) =
diff --git a/AWS/EC2/Internal.hs b/AWS/EC2/Internal.hs
--- a/AWS/EC2/Internal.hs
+++ b/AWS/EC2/Internal.hs
@@ -24,9 +24,9 @@
 import Control.Applicative
 import Data.Conduit
 import qualified Data.Conduit.List as CL
+import Data.Maybe (fromMaybe)
 import Data.XML.Types (Event)
 import Data.Text (Text)
-import Data.Maybe (fromMaybe)
 
 import AWS.Class
 import AWS.Credential
@@ -52,33 +52,33 @@
 
 itemConduit :: MonadThrow m
     => Text
-    -> GLSink Event m o
-    -> GLConduit Event m o
+    -> Consumer Event m o
+    -> Conduit Event m o
 itemConduit tag inner =
     fromMaybe (()) <$> elementM tag (listConduit "item" inner)
 
 itemsSet :: MonadThrow m
     => Text
-    -> GLSink Event m o
-    -> GLSink Event m [o]
-itemsSet tag inner = itemConduit tag inner >+> CL.consume
+    -> Consumer Event m o
+    -> Consumer Event m [o]
+itemsSet tag inner = itemConduit tag inner =$= CL.consume
 
 resourceTagSink :: MonadThrow m
-    => GLSink Event m [ResourceTag]
+    => Consumer Event m [ResourceTag]
 resourceTagSink = itemsSet "tagSet" $
     ResourceTag
     <$> getT "key"
     <*> getT "value"
 
 productCodeSink :: MonadThrow m
-    => GLSink Event m [ProductCode]
+    => Consumer Event m [ProductCode]
 productCodeSink = itemsSet "productCodes" $
     ProductCode
     <$> getT "productCode"
     <*> getT "type"
 
 stateReasonSink :: MonadThrow m
-    => GLSink Event m (Maybe StateReason)
+    => Consumer Event m (Maybe StateReason)
 stateReasonSink = elementM "stateReason" $
     StateReason
     <$> getT "code"
@@ -90,17 +90,17 @@
 volumeType t _ = monadThrow $ FromTextError t
 
 volumeTypeSink :: MonadThrow m
-    => Pipe Event Event o u m VolumeType
+    => Consumer Event m VolumeType
 volumeTypeSink = volumeType <$> getT "volumeType" <*> getT "iops" >>= lift
 
-groupSetSink :: MonadThrow m => GLSink Event m [Group]
+groupSetSink :: MonadThrow m => Consumer Event m [Group]
 groupSetSink = itemsSet "groupSet" $ Group
     <$> getT "groupId"
     <*> getT "groupName"
 
 networkInterfaceAttachmentSink
     :: MonadThrow m
-    => GLSink Event m (Maybe NetworkInterfaceAttachment)
+    => Consumer Event m (Maybe NetworkInterfaceAttachment)
 networkInterfaceAttachmentSink = elementM "attachment" $
     NetworkInterfaceAttachment
     <$> getT "attachmentId"
diff --git a/AWS/EC2/KeyPair.hs b/AWS/EC2/KeyPair.hs
--- a/AWS/EC2/KeyPair.hs
+++ b/AWS/EC2/KeyPair.hs
@@ -32,7 +32,7 @@
         , filtersParam filters
         ]
 
-keyPairSink :: MonadThrow m => GLSink Event m KeyPair
+keyPairSink :: MonadThrow m => Consumer Event m KeyPair
 keyPairSink = KeyPair
     <$> getT "keyName"
     <*> getT "keyFingerprint"
diff --git a/AWS/EC2/Metadata.hs b/AWS/EC2/Metadata.hs
--- a/AWS/EC2/Metadata.hs
+++ b/AWS/EC2/Metadata.hs
@@ -56,8 +56,8 @@
 query path = runResourceT $ do
     req <- liftIO $ parseUrl (base <> path)
     mgr <- liftIO $ newManager def
-    Response _ _ _ res <- http req mgr
-    res $$+- CB.lines =$ CL.consume
+    res <- http req mgr
+    responseBody res $$+- CB.lines =$ CL.consume
 
 latestVersion :: IO Text
 latestVersion = bsToText . last . init <$> query ""
@@ -156,8 +156,8 @@
 queryRaw path = runResourceT $ do
     req <- liftIO $ parseUrl (base <> path)
     mgr <- liftIO $ newManager def
-    Response _ _ _ res <- http req mgr
-    mconcat <$> (res $$+- CL.consume)
+    res <- http req mgr
+    mconcat <$> (responseBody res $$+- CL.consume)
 
 identity :: String -> IO Text
 identity name =
diff --git a/AWS/EC2/NetworkInterface.hs b/AWS/EC2/NetworkInterface.hs
--- a/AWS/EC2/NetworkInterface.hs
+++ b/AWS/EC2/NetworkInterface.hs
@@ -68,7 +68,7 @@
 
 networkInterfaceSink
     :: MonadThrow m
-    => GLSink Event m NetworkInterface
+    => Consumer Event m NetworkInterface
 networkInterfaceSink = NetworkInterface
     <$> getT "networkInterfaceId"
     <*> getT "subnetId"
@@ -97,7 +97,7 @@
 
 networkInterfaceAssociationSink
     :: MonadThrow m
-    => GLSink Event m (Maybe NetworkInterfaceAssociation)
+    => Consumer Event m (Maybe NetworkInterfaceAssociation)
 networkInterfaceAssociationSink =
     elementM "association" $ NetworkInterfaceAssociation
         <$> getT "attachmentId"
diff --git a/AWS/EC2/NetworkInterfaceAttribute.hs b/AWS/EC2/NetworkInterfaceAttribute.hs
--- a/AWS/EC2/NetworkInterfaceAttribute.hs
+++ b/AWS/EC2/NetworkInterfaceAttribute.hs
@@ -12,7 +12,7 @@
    ) where
 
 import Data.Text (Text)
-import Data.Conduit (GLSink, MonadBaseControl, MonadResource)
+import Data.Conduit (Consumer, MonadBaseControl, MonadResource)
 import Data.XML.Types (Event)
 
 import AWS.EC2.Internal (EC2, groupSetSink, networkInterfaceAttachmentSink)
@@ -50,7 +50,7 @@
 describeNetworkInterfaceAttribute
     :: (MonadBaseControl IO m, MonadResource m)
     => Text
-    -> GLSink Event m a
+    -> Consumer Event m a
     -> Text
     -> EC2 m a
 describeNetworkInterfaceAttribute action sink networkInterface =
diff --git a/AWS/EC2/PlacementGroup.hs b/AWS/EC2/PlacementGroup.hs
--- a/AWS/EC2/PlacementGroup.hs
+++ b/AWS/EC2/PlacementGroup.hs
@@ -30,7 +30,7 @@
         , filtersParam filters
         ]
 
-placementGroupSink :: MonadThrow m => GLSink Event m PlacementGroup
+placementGroupSink :: MonadThrow m => Consumer Event m PlacementGroup
 placementGroupSink =
     PlacementGroup
     <$> getT "groupName"
diff --git a/AWS/EC2/Query.hs b/AWS/EC2/Query.hs
--- a/AWS/EC2/Query.hs
+++ b/AWS/EC2/Query.hs
@@ -33,13 +33,13 @@
 apiVersion = "2012-12-01"
 
 sinkRequestId :: MonadThrow m
-    => GLSink Event m (Maybe Text)
+    => Consumer Event m (Maybe Text)
 sinkRequestId = do
     await -- EventBeginDocument
     await -- EventBeginElement DescribeImagesResponse
     getT "requestId"
 
-sinkError :: MonadThrow m => ByteString -> Int -> GLSink Event m a
+sinkError :: MonadThrow m => ByteString -> Int -> Consumer Event m a
 sinkError a s = do
     await
     element "Response" $ do
@@ -52,7 +52,7 @@
     :: (MonadResource m, MonadBaseControl IO m)
     => ByteString
     -> [QueryParam]
-    -> GLSink Event m o
+    -> Consumer Event m o
     -> EC2 m o
 ec2Query action params sink = do
     src <- ec2QuerySource action params $ sink >>= yield
diff --git a/AWS/EC2/Region.hs b/AWS/EC2/Region.hs
--- a/AWS/EC2/Region.hs
+++ b/AWS/EC2/Region.hs
@@ -28,7 +28,7 @@
         , filtersParam filters
         ]
     regionInfoConduit :: MonadThrow m
-        => GLConduit Event m Region
+        => Conduit Event m Region
     regionInfoConduit = itemConduit "regionInfo" $
         Region
         <$> getT "regionName"
diff --git a/AWS/EC2/RouteTable.hs b/AWS/EC2/RouteTable.hs
--- a/AWS/EC2/RouteTable.hs
+++ b/AWS/EC2/RouteTable.hs
@@ -37,7 +37,7 @@
         ]
 
 routeTableSink :: MonadThrow m
-    => GLSink Event m RouteTable
+    => Consumer Event m RouteTable
 routeTableSink = RouteTable
     <$> getT "routeTableId"
     <*> getT "vpcId"
@@ -47,7 +47,7 @@
     <*> resourceTagSink
 
 routeSink :: MonadThrow m
-    => GLSink Event m [Route]
+    => Consumer Event m [Route]
 routeSink = itemsSet "routeSet" $ Route
     <$> getT "destinationCidrBlock"
     <*> getT "gatewayId"
@@ -58,7 +58,7 @@
     <*> getT "origin"
 
 routeTableAssociationSink :: MonadThrow m
-    => GLSink Event m [RouteTableAssociation]
+    => Consumer Event m [RouteTableAssociation]
 routeTableAssociationSink = itemsSet "associationSet" $ RouteTableAssociation
     <$> getT "routeTableAssociationId"
     <*> getT "routeTableId"
diff --git a/AWS/EC2/SecurityGroup.hs b/AWS/EC2/SecurityGroup.hs
--- a/AWS/EC2/SecurityGroup.hs
+++ b/AWS/EC2/SecurityGroup.hs
@@ -49,7 +49,7 @@
         ]
 
 ipPermissionsSink :: MonadThrow m
-    => Text -> GLSink Event m [IpPermission]
+    => Text -> Consumer Event m [IpPermission]
 ipPermissionsSink name = itemsSet name $ IpPermission
     <$> getT "ipProtocol"
     <*> getT "fromPort"
@@ -93,7 +93,6 @@
 securityGroupRequestParam (SecurityGroupRequestGroupName t) =
     "GroupName" |= t
 
--- | not tested
 authorizeSecurityGroupIngress
     :: (MonadResource m, MonadBaseControl IO m)
     => SecurityGroupRequest
@@ -102,7 +101,6 @@
 authorizeSecurityGroupIngress =
     securityGroupQuery "AuthorizeSecurityGroupIngress"
 
--- | not tested
 authorizeSecurityGroupEgress
     :: (MonadResource m, MonadBaseControl IO m)
     => Text -- ^ GroupId
@@ -112,7 +110,6 @@
     securityGroupQuery "AuthorizeSecurityGroupEgress"
         $ SecurityGroupRequestGroupId gid
 
--- | not tested
 revokeSecurityGroupIngress
     :: (MonadResource m, MonadBaseControl IO m)
     => SecurityGroupRequest
@@ -121,7 +118,6 @@
 revokeSecurityGroupIngress =
     securityGroupQuery "RevokeSecurityGroupIngress"
 
--- | not tested
 revokeSecurityGroupEgress
     :: (MonadResource m, MonadBaseControl IO m)
     => Text -- ^ GroupId
@@ -156,6 +152,6 @@
   where
     groupPairParams gp =
         [ "UserId" |=? userIdGroupPairUserId gp
-        , "GroupId" |= userIdGroupPairGroupId gp
+        , "GroupId" |=? userIdGroupPairGroupId gp
         , "GroupName" |=? userIdGroupPairGroupName gp
         ]
diff --git a/AWS/EC2/Snapshot.hs b/AWS/EC2/Snapshot.hs
--- a/AWS/EC2/Snapshot.hs
+++ b/AWS/EC2/Snapshot.hs
@@ -39,7 +39,7 @@
         ]
 
 snapshotSink :: MonadThrow m
-    => GLSink Event m Snapshot
+    => Consumer Event m Snapshot
 snapshotSink = Snapshot
         <$> getT "snapshotId"
         <*> getT "volumeId"
@@ -107,16 +107,19 @@
 
 snapshotAttributeSink
     :: MonadThrow m
-    => GLSink Event m SnapshotAttribute
+    => Consumer Event m SnapshotAttribute
 snapshotAttributeSink = SnapshotAttribute
     <$> getT "snapshotId"
-    <*> itemsSet "createVolumePermission" (
-        CreateVolumePermissionItem
-        <$> getT "userId"
-        <*> getT "group"
-        )
+    <*> itemsSet "createVolumePermission" createVolumePermissionItemSink
     <*> productCodeSink
 
+createVolumePermissionItemSink :: MonadThrow m => Consumer Event m CreateVolumePermissionItem
+createVolumePermissionItemSink = do
+    mg <- elementM "group" text
+    case mg of
+        Just g -> return $ CreateVolumePermissionItemGroup g
+        Nothing -> CreateVolumePermissionItemUserId <$> getT "userId"
+
 modifySnapshotAttribute
     :: (MonadResource m, MonadBaseControl IO m)
     => Text -- ^ SnapshotId
@@ -138,10 +141,8 @@
     , "Remove" |.#. itemParams <$> createVolumePermissionRemove cvp
     ]
   where
-    itemParams item =
-        [ "UserId" |=? createVolumePermissionItemUserId item
-        , "Group" |=? createVolumePermissionItemGroup item
-        ]
+    itemParams (CreateVolumePermissionItemUserId u) = ["UserId" |= u]
+    itemParams (CreateVolumePermissionItemGroup g) = ["Group" |= g]
 
 resetSnapshotAttribute
     :: (MonadResource m, MonadBaseControl IO m)
diff --git a/AWS/EC2/Subnets.hs b/AWS/EC2/Subnets.hs
--- a/AWS/EC2/Subnets.hs
+++ b/AWS/EC2/Subnets.hs
@@ -35,7 +35,7 @@
         ]
 
 subnetSink :: MonadThrow m
-    => GLSink Event m Subnet
+    => Consumer Event m Subnet
 subnetSink = Subnet
     <$> getT "subnetId"
     <*> getT "state"
diff --git a/AWS/EC2/Types/Address.hs b/AWS/EC2/Types/Address.hs
--- a/AWS/EC2/Types/Address.hs
+++ b/AWS/EC2/Types/Address.hs
@@ -60,6 +60,6 @@
 
 data DisassociateAddressRequest
     = DisassociateAddressRequestEc2 IPv4 -- ^ PublicIp for EC2
-    | DisassociateAddressRequestVpc IPv4
+    | DisassociateAddressRequestVpc Text -- ^ AssociationId for VPC
       -- ^ AssociationId for VPC
   deriving (Show, Read, Eq)
diff --git a/AWS/EC2/Types/Image.hs b/AWS/EC2/Types/Image.hs
--- a/AWS/EC2/Types/Image.hs
+++ b/AWS/EC2/Types/Image.hs
@@ -123,10 +123,9 @@
     }
   deriving (Show, Read, Eq)
 
-data LaunchPermissionItem = LaunchPermissionItem
-    { launchPermissionItemGroup :: Text
-    , launchPermissionUserId :: Text
-    }
+data LaunchPermissionItem
+    = LaunchPermissionItemGroup Text
+    | LaunchPermissionItemUserId Text
   deriving (Show, Read, Eq)
 
 data ProductCodeItem = ProductCodeItem
diff --git a/AWS/EC2/Types/SecurityGroup.hs b/AWS/EC2/Types/SecurityGroup.hs
--- a/AWS/EC2/Types/SecurityGroup.hs
+++ b/AWS/EC2/Types/SecurityGroup.hs
@@ -36,7 +36,7 @@
 
 data UserIdGroupPair = UserIdGroupPair
     { userIdGroupPairUserId :: Maybe Text
-    , userIdGroupPairGroupId :: Text
+    , userIdGroupPairGroupId :: Maybe Text
     , userIdGroupPairGroupName :: Maybe Text
     }
   deriving (Show, Read, Eq)
diff --git a/AWS/EC2/Types/Snapshot.hs b/AWS/EC2/Types/Snapshot.hs
--- a/AWS/EC2/Types/Snapshot.hs
+++ b/AWS/EC2/Types/Snapshot.hs
@@ -19,10 +19,9 @@
     }
   deriving (Show, Read, Eq)
 
-data CreateVolumePermissionItem = CreateVolumePermissionItem
-    { createVolumePermissionItemUserId :: Maybe Text
-    , createVolumePermissionItemGroup :: Maybe Text
-    }
+data CreateVolumePermissionItem
+    = CreateVolumePermissionItemUserId Text
+    | CreateVolumePermissionItemGroup Text
   deriving (Show, Read, Eq)
 
 data ResetSnapshotAttributeRequest
diff --git a/AWS/EC2/Types/Subnets.hs b/AWS/EC2/Types/Subnets.hs
--- a/AWS/EC2/Types/Subnets.hs
+++ b/AWS/EC2/Types/Subnets.hs
@@ -19,7 +19,7 @@
 data Subnet = Subnet
     { subnetId :: Text
     , subnetState :: SubnetState
-    , subnetVpicId :: Text
+    , subnetVpcId :: Text
     , subnetCidrBlock :: AddrRange IPv4
     , subnetAvailableIpAddressCount :: Int
     , subnetAvailabilityZone :: Text
diff --git a/AWS/EC2/Types/VPC.hs b/AWS/EC2/Types/VPC.hs
--- a/AWS/EC2/Types/VPC.hs
+++ b/AWS/EC2/Types/VPC.hs
@@ -125,7 +125,7 @@
     , vpnConnectionTagSet :: [ResourceTag]
     , vpnConnectionVgwTelemetry :: [VpnTunnelTelemetry]
     , vpnConnectionOptions :: Maybe VpnConnectionOptionsRequest
-    , vpnConnectionRoutes :: Maybe VpnStaticRoute
+    , vpnConnectionRoutes :: [VpnStaticRoute]
     }
   deriving (Show, Read, Eq)
 
@@ -179,7 +179,7 @@
     { vpnTunnelTelemetryOutsideIpAddress :: IPv4
     , vpnTunnelTelemetryStatus :: VpnTunnelTelemetryStatus
     , vpnTunnelTelemetryLastStatusChange :: UTCTime
-    , vpnTunnelTelemetryStatusMessage :: Text
+    , vpnTunnelTelemetryStatusMessage :: Maybe Text
     , vpnTunnelTelemetryAcceptRouteCount :: Int
     }
   deriving (Show, Read, Eq)
@@ -200,7 +200,7 @@
     ["pending", "available", "deleting", "deleted"]
 deriveFromText "VpnGatewayState"
     ["pending", "available", "deleting", "deleted"]
-deriveFromText "VpnStaticRouteSource" ["Static"]
+deriveFromText "VpnStaticRouteSource" ["static"]
 deriveFromText "VpnStaticRouteState"
     ["pending", "available", "deleting", "deleted"]
 deriveFromText "VpnTunnelTelemetryStatus" ["UP", "DOWN"]
diff --git a/AWS/EC2/Util.hs b/AWS/EC2/Util.hs
--- a/AWS/EC2/Util.hs
+++ b/AWS/EC2/Util.hs
@@ -104,7 +104,7 @@
         Just r  -> if f r
             then return r
             else do
-                liftIO $ CC.threadDelay 5
+                sleep 5
                 wait f g rid
 
 findTag
diff --git a/AWS/EC2/VPC.hs b/AWS/EC2/VPC.hs
--- a/AWS/EC2/VPC.hs
+++ b/AWS/EC2/VPC.hs
@@ -3,14 +3,17 @@
 module AWS.EC2.VPC
     ( associateDhcpOptions
     , attachInternetGateway
+    , attachVpnGateway
     , createVpc
     , createVpnConnection
+    , createVpnConnectionRoute
     , createVpnGateway
     , createCustomerGateway
     , createInternetGateway
     , createDhcpOptions
     , deleteVpc
     , deleteVpnConnection
+    , deleteVpnConnectionRoute
     , deleteVpnGateway
     , deleteCustomerGateway
     , deleteInternetGateway
@@ -22,6 +25,9 @@
     , describeInternetGateways
     , describeDhcpOptions
     , detachInternetGateway
+    , detachVpnGateway
+    , disableVgwRoutePropagation
+    , enableVgwRoutePropagation
     ) where
 
 import Data.Text (Text)
@@ -51,6 +57,19 @@
         [ "InternetGatewayId" |= internetGatewayId
         , "VpcId" |= vid ]
 
+attachVpnGateway
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the virtual private gateway.
+    -> Text -- ^ The ID of the VPC.
+    -> EC2 m Attachment
+attachVpnGateway vgw vpc =
+    ec2Query "AttachVpnGateway" params $ element "attachment" attachmentSink
+  where
+    params =
+        [ "VpnGatewayId" |= vgw
+        , "VpcId" |= vpc
+        ]
+
 ------------------------------------------------------------
 -- detachInternetGateway
 ------------------------------------------------------------
@@ -66,6 +85,19 @@
         [ "InternetGatewayId" |= internetGatewayId
         , "VpcId" |= vid ]
 
+detachVpnGateway
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the virtual private gateway.
+    -> Text -- ^ The ID of the VPC.
+    -> EC2 m Bool
+detachVpnGateway vgw vpc =
+    ec2Query "DetachVpnGateway" params $ getT "return"
+  where
+    params =
+        [ "VpnGatewayId" |= vgw
+        , "VpcId" |= vpc
+        ]
+
 ------------------------------------------------------------
 -- deleteInternetGateway
 ------------------------------------------------------------
@@ -103,14 +135,14 @@
         ]
 
 internetGatewaySink :: MonadThrow m
-    => GLSink Event m InternetGateway
+    => Consumer Event m InternetGateway
 internetGatewaySink = InternetGateway
     <$> getT "internetGatewayId"
     <*> itemsSet "attachmentSet" internetGatewayAttachmentSink
     <*> resourceTagSink
 
 internetGatewayAttachmentSink :: MonadThrow m
-    => GLSink Event m InternetGatewayAttachment
+    => Consumer Event m InternetGatewayAttachment
 internetGatewayAttachmentSink = InternetGatewayAttachment
     <$> getT "vpcId"
     <*> getT "state"
@@ -134,7 +166,7 @@
 
 vpnConnectionSink
     :: MonadThrow m
-    => GLSink Event m VpnConnection
+    => Consumer Event m VpnConnection
 vpnConnectionSink = VpnConnection
     <$> getT "vpnConnectionId"
     <*> getT "state"
@@ -155,7 +187,7 @@
         (VpnConnectionOptionsRequest
         <$> getT "staticRoutesOnly"
         )
-    <*> elementM "routes"
+    <*> itemsSet "routes"
         (VpnStaticRoute
         <$> getT "destinationCidrBlock"
         <*> getT "source"
@@ -185,6 +217,19 @@
         , "Options" |.+ "StaticRoutesOnly" |=? boolToText <$> option
         ]
 
+createVpnConnectionRoute
+    :: (MonadBaseControl IO m, MonadResource m)
+    => AddrRange IPv4 -- ^ The CIDR block associated with the local subnet of the customer data center.
+    -> Text -- ^ The ID of the VPN connection.
+    -> EC2 m Bool
+createVpnConnectionRoute cidr vpnConn =
+    ec2Query "CreateVpnConnectionRoute" params $ getT "return"
+  where
+    params =
+        [ "DestinationCidrBlock" |= toText cidr
+        , "VpnConnectionId" |= vpnConn
+        ]
+
 ------------------------------------------------------------
 -- deleteVpnConnection
 ------------------------------------------------------------
@@ -194,6 +239,19 @@
     -> EC2 m Bool
 deleteVpnConnection = ec2Delete "DeleteVpnConnection" "VpnConnectionId"
 
+deleteVpnConnectionRoute
+    :: (MonadBaseControl IO m, MonadResource m)
+    => AddrRange IPv4 -- ^ The CIDR block associated with the local subnet of the customer data center.
+    -> Text -- ^ The ID of the VPN connection.
+    -> EC2 m Bool
+deleteVpnConnectionRoute cidr vpnConn =
+    ec2Query "DeleteVpnConnectionRoute" params $ getT "return"
+  where
+    params =
+        [ "DestinationCidrBlock" |= toText cidr
+        , "VpnConnectionId" |= vpnConn
+        ]
+
 ------------------------------------------------------------
 -- describeVpcs
 ------------------------------------------------------------
@@ -212,7 +270,7 @@
         ]
 
 vpcSink :: MonadThrow m
-    => GLSink Event m Vpc
+    => Consumer Event m Vpc
 vpcSink = Vpc
     <$> getT "vpcId"
     <*> getT "state"
@@ -266,7 +324,7 @@
         ]
 
 vpnGatewaySink :: MonadThrow m
-    => GLSink Event m VpnGateway
+    => Consumer Event m VpnGateway
 vpnGatewaySink = VpnGateway
     <$> getT "vpnGatewayId"
     <*> getT "state"
@@ -276,7 +334,7 @@
     <*> resourceTagSink
 
 attachmentSink :: MonadThrow m
-    => GLSink Event m Attachment
+    => Consumer Event m Attachment
 attachmentSink = Attachment
     <$> getT "vpcId"
     <*> getT "state"
@@ -326,7 +384,7 @@
         ]
 
 customerGatewaySink :: MonadThrow m
-    => GLSink Event m CustomerGateway
+    => Consumer Event m CustomerGateway
 customerGatewaySink = CustomerGateway
     <$> getT "customerGatewayId"
     <*> getT "state"
@@ -381,14 +439,14 @@
         ]
 
 dhcpOptionsSink :: MonadThrow m
-    => GLSink Event m DhcpOptions
+    => Consumer Event m DhcpOptions
 dhcpOptionsSink = DhcpOptions
     <$> getT "dhcpOptionsId"
     <*> itemsSet "dhcpConfigurationSet" dhcpConfigurationSink
     <*> resourceTagSink
 
 dhcpConfigurationSink :: MonadThrow m
-    => GLSink Event m DhcpConfiguration
+    => Consumer Event m DhcpConfiguration
 dhcpConfigurationSink = DhcpConfiguration
     <$> getT "key"
     <*> itemsSet "valueSet"
@@ -439,4 +497,30 @@
     params =
         [ "DhcpOptionsId" |= doid
         , "VpcId" |= vpcid
+        ]
+
+enableVgwRoutePropagation
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the routing table.
+    -> Text -- ^ The ID of the virtual private gateway.
+    -> EC2 m Bool
+enableVgwRoutePropagation rtb vgw =
+    ec2Query "EnableVgwRoutePropagation" params $ getT "return"
+  where
+    params =
+        [ "RouteTableId" |= rtb
+        , "GatewayId" |= vgw
+        ]
+
+disableVgwRoutePropagation
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the routing table.
+    -> Text -- ^ The ID of the virtual private gateway.
+    -> EC2 m Bool
+disableVgwRoutePropagation rtb vgw =
+    ec2Query "DisableVgwRoutePropagation" params $ getT "return"
+  where
+    params =
+        [ "RouteTableId" |= rtb
+        , "GatewayId" |= vgw
         ]
diff --git a/AWS/EC2/Volume.hs b/AWS/EC2/Volume.hs
--- a/AWS/EC2/Volume.hs
+++ b/AWS/EC2/Volume.hs
@@ -39,7 +39,7 @@
         ]
 
 volumeSink :: MonadThrow m
-    => GLSink Event m Volume
+    => Consumer Event m Volume
 volumeSink = Volume
     <$> getT "volumeId"
     <*> getT "size"
@@ -51,7 +51,7 @@
     <*> resourceTagSink
     <*> volumeTypeSink
 
-attachmentSink :: MonadThrow m => GLSink Event m AttachmentSetItemResponse
+attachmentSink :: MonadThrow m => Consumer Event m AttachmentSetItemResponse
 attachmentSink = AttachmentSetItemResponse
     <$> getT "volumeId"
     <*> getT "instanceId"
@@ -134,7 +134,7 @@
         ]
 
 volumeStatusSink :: MonadThrow m
-    => GLSink Event m VolumeStatus
+    => Consumer Event m VolumeStatus
 volumeStatusSink = VolumeStatus
     <$> getT "volumeId"
     <*> getT "availabilityZone"
@@ -202,7 +202,7 @@
 volumeAttributeSink
     :: MonadThrow m
     => VolumeAttributeRequest
-    -> GLSink Event m VolumeAttribute
+    -> Consumer Event m VolumeAttribute
 volumeAttributeSink VolumeAttributeRequestAutoEnableIO
     = VolumeAttributeAutoEnableIO
     <$> element "autoEnableIO" (getT "value")
diff --git a/AWS/ELB/Internal.hs b/AWS/ELB/Internal.hs
--- a/AWS/ELB/Internal.hs
+++ b/AWS/ELB/Internal.hs
@@ -20,6 +20,6 @@
     :: (MonadBaseControl IO m, MonadResource m)
     => ByteString -- ^ Action
     -> [QueryParam]
-    -> GLSink Event m a
+    -> Consumer Event m a
     -> AWS AWSContext m a
 elbQuery = commonQuery apiVersion
diff --git a/AWS/ELB/LoadBalancer.hs b/AWS/ELB/LoadBalancer.hs
--- a/AWS/ELB/LoadBalancer.hs
+++ b/AWS/ELB/LoadBalancer.hs
@@ -54,7 +54,7 @@
         ]
 
 sinkLoadBalancers :: MonadThrow m
-    => GLSink Event m [LoadBalancer]
+    => Consumer Event m [LoadBalancer]
 sinkLoadBalancers = members "LoadBalancerDescriptions" $
     LoadBalancer
     <$> members "SecurityGroups" text
@@ -106,10 +106,10 @@
         )
     <*> members "Subnets" text
 
-sinkInstance :: MonadThrow m => GLSink Event m Instance
+sinkInstance :: MonadThrow m => Consumer Event m Instance
 sinkInstance = Instance <$> getT "InstanceId"
 
-sinkHealthCheck :: MonadThrow m => GLSink Event m HealthCheck
+sinkHealthCheck :: MonadThrow m => Consumer Event m HealthCheck
 sinkHealthCheck =
     HealthCheck
     <$> getT "Interval"
@@ -287,14 +287,14 @@
         , "PolicyNames.member" |.#= policies
         ]
 
-sinkPolicyDescription :: MonadThrow m => GLSink Event m PolicyDescription
+sinkPolicyDescription :: MonadThrow m => Consumer Event m PolicyDescription
 sinkPolicyDescription =
     PolicyDescription
     <$> getT "PolicyName"
     <*> getT "PolicyTypeName"
     <*> members "PolicyAttributeDescriptions" sinkPolicyAttribute
 
-sinkPolicyAttribute :: MonadThrow m => GLSink Event m PolicyAttribute
+sinkPolicyAttribute :: MonadThrow m => Consumer Event m PolicyAttribute
 sinkPolicyAttribute =
     PolicyAttribute
     <$> getT "AttributeName"
@@ -309,14 +309,14 @@
   where
     params = ["PolicyTypeNames.member" |.#= typeNames]
 
-sinkPolicyType :: MonadThrow m => GLSink Event m PolicyType
+sinkPolicyType :: MonadThrow m => Consumer Event m PolicyType
 sinkPolicyType =
     PolicyType
     <$> members "PolicyAttributeTypeDescriptions" sinkPolicyAttributeType
     <*> getT "PolicyTypeName"
     <*> getT "Description"
 
-sinkPolicyAttributeType :: MonadThrow m => GLSink Event m PolicyAttributeType
+sinkPolicyAttributeType :: MonadThrow m => Consumer Event m PolicyAttributeType
 sinkPolicyAttributeType =
     PolicyAttributeType
     <$> getT "AttributeName"
@@ -374,7 +374,7 @@
         , "LoadBalancerName" |= lb
         ]
 
-sinkInstanceState :: MonadThrow m => GLSink Event m InstanceState
+sinkInstanceState :: MonadThrow m => Consumer Event m InstanceState
 sinkInstanceState =
     InstanceState
     <$> getT "Description"
@@ -432,7 +432,7 @@
 
 createLBCookieStickinessPolicy
     :: (MonadBaseControl IO m, MonadResource m)
-    => Maybe Int -- ^ The time period in seconds after which the cookie should be considered stale. Not specifying this parameter indicates that the sticky session will last for the duration of the browser session. 
+    => Maybe Int -- ^ The time period in seconds after which the cookie should be considered stale. Not specifying this parameter indicates that the sticky session will last for the duration of the browser session.
     -> Text -- ^ The name associated with the LoadBalancer.
     -> Text -- ^ The name of the policy being created.
     -> ELB m ()
diff --git a/AWS/Lib/Parser.hs b/AWS/Lib/Parser.hs
--- a/AWS/Lib/Parser.hs
+++ b/AWS/Lib/Parser.hs
@@ -22,10 +22,15 @@
 
 import Data.XML.Types (Event(..), Name(..))
 import Data.ByteString (ByteString)
+import Data.Char (isSpace)
 import Data.Conduit
+import Data.Conduit.Internal (ConduitM)
 import qualified Data.Conduit.List as CL
+import qualified Data.Text as T
 import qualified Text.XML.Stream.Parse as XML
+import Data.XML.Types (Content(..))
 import Control.Applicative
+import Control.Monad (when, void)
 import Data.Monoid ((<>))
 import Control.Monad.Trans.Class (lift)
 import Data.Maybe (fromMaybe)
@@ -35,39 +40,43 @@
 
 type RequestId = Text
 
-text :: MonadThrow m => GLSink Event m Text
+text :: MonadThrow m => Consumer Event m Text
 text = XML.content
 
+whenM :: Monad m => m (Maybe a) -> (a -> m ()) -> m ()
+whenM mma f = mma >>= maybe (return ()) f
+
+fromMaybeM :: Monad m => m a -> Maybe a -> m a
+fromMaybeM a Nothing  = a
+fromMaybeM _ (Just a) = return a
+
 listConduit :: MonadThrow m
     => Text
-    -> GLSink Event m o
-    -> GLConduit Event m o
-listConduit name p =
-    awaitWhile isTag >>= maybe (return ()) (\e -> do
-        leftover e
-        if isBeginTagName name e
-            then do
-                element name $ p >>= yield
-                listConduit name p
-            else return ()
-        )
+    -> Consumer Event m o
+    -> Conduit Event m o
+listConduit name p = whenM (awaitWhile isTag) $ \e -> do
+    leftover e
+    when (isBeginTagName name e) $
+        whenM (elementM name p) $ \a -> do
+            yield a
+            listConduit name p
 
 listConsumer :: MonadThrow m
     => Text
-    -> GLSink Event m o
-    -> GLSink Event m [o]
-listConsumer name p = listConduit name p >+> CL.consume
+    -> Consumer Event m o
+    -> Consumer Event m [o]
+listConsumer name p = listConduit name p =$= CL.consume
 
 isTag :: Event -> Bool
 isTag (EventBeginElement _ _) =True
 isTag (EventEndElement _) =True
 isTag _ = False
 
-sinkDropWhile :: Monad m => (i -> Bool) -> GLSink i m ()
-sinkDropWhile f = await >>= maybe (return ()) g
+sinkDropWhile :: Monad m => (i -> Bool) -> Consumer i m ()
+sinkDropWhile f = whenM await g
   where
-      g i | f i       = sinkDropWhile f
-              | otherwise = leftover i >> return ()
+    g i | f i       = sinkDropWhile f
+        | otherwise = void $ leftover i
 
 isBeginTagName :: Text -> Event -> Bool
 isBeginTagName name (EventBeginElement n _)
@@ -77,7 +86,7 @@
 
 awaitWhile :: Monad m
     => (i -> Bool)
-    -> Pipe l i o u m (Maybe i)
+    -> Consumer i m (Maybe i)
 awaitWhile f = await >>= g
   where
     g Nothing       = return Nothing
@@ -87,36 +96,36 @@
 
 getT :: (MonadThrow m, FromText a)
     => Text
-    -> Pipe Event Event o u m a
+    -> Consumer Event m a
 getT name = elementM name text >>= lift . fromMaybeText name
 
-getT_ :: forall m o u . MonadThrow m
+getT_ :: forall m . MonadThrow m
     => Text
-    -> Pipe Event Event o u m ()
-getT_ name = () <$ (getT name :: Pipe Event Event o u m (Maybe Text))
+    -> Consumer Event m ()
+getT_ name = () <$ (getT name :: Consumer Event m (Maybe Text))
 
-elementM :: forall o u m a . MonadThrow m
+elementM :: MonadThrow m
     => Text
-    -> Pipe Event Event o u m a
-    -> Pipe Event Event o u m (Maybe a)
+    -> ConduitM Event o m a
+    -> ConduitM Event o m (Maybe a)
 elementM name inner = do
     sinkDropWhile $ not . isTag
-    XML.tagPredicate g (return ()) $ const inner
+    tagConduitM g inner
   where
-    g n = (nameLocalName n == name)
+    g n = nameLocalName n == name
 
-element :: forall o u m a . MonadThrow m
+element :: MonadThrow m
     => Text
-    -> Pipe Event Event o u m a
-    -> Pipe Event Event o u m a
+    -> Consumer Event m a
+    -> Consumer Event m a
 element name inner = elementM name inner >>=
-    maybe (lift $ monadThrow $ ResponseParseError name) return
+    fromMaybeM (lift $ monadThrow $ ResponseParseError name)
 
 sinkResponse
     :: MonadThrow m
     => Text -- ^ Action
-    -> GLSink Event m a
-    -> GLSink Event m (a, RequestId)
+    -> Consumer Event m a
+    -> Consumer Event m (a, RequestId)
 sinkResponse action sink = do
     sinkEventBeginDocument
     element (action <> "Response") $ (,)
@@ -125,18 +134,18 @@
   where
     sinkResult =
         elementM (action <> "Result") sink -- XXX: parse Marker. This marker may not occur (e.g., PutMetricAlarm).
-        >>= maybe sink return
+        >>= fromMaybeM sink
 
 sinkResponseMetadata
     :: MonadThrow m
-    => GLSink Event m Text
+    => Consumer Event m Text
 sinkResponseMetadata =
     element "ResponseMetadata" $
         getT "RequestId"
 
 sinkEventBeginDocument
     :: MonadThrow m
-    => GLSink Event m ()
+    => Consumer Event m ()
 sinkEventBeginDocument = do
     me <- await
     case me of
@@ -144,17 +153,60 @@
         Just EventBeginDocument -> return ()
         Just _ -> fail $ "unexpected: " <> show me
 
-sinkError :: MonadThrow m => ByteString -> Int -> GLSink Event m a
+sinkError :: MonadThrow m => ByteString -> Int -> Consumer Event m a
 sinkError action status = element "ErrorResponse" $ do
     (c,m) <- element "Error" $ (,)
         <$> (getT_ "Type" *> getT "Code")
         <*> getT "Message"
     rid <- getT "RequestId"
-    lift $ monadThrow $ ClientError action status c m rid
+    lift $ monadThrow $ errorData action status c m rid
+  where
+    errorData = if status < 500 then ClientError else ServerError
 
 members :: MonadThrow m
     => Text
-    -> GLSink Event m a
-    -> GLSink Event m [a]
-members name f = 
+    -> Consumer Event m a
+    -> Consumer Event m [a]
+members name f =
     fromMaybe [] <$> elementM name (listConsumer "member" f)
+
+-- | Text.XML.Stream.Parse.tag using ConduitM
+tagConduitM :: MonadThrow m
+    => (Name -> Bool)
+    -> ConduitM Event o m c
+    -> ConduitM Event o m (Maybe c)
+tagConduitM checkName inner = do
+    x <- dropWS
+    case x of
+        Just (EventBeginElement name _) ->
+            if checkName name
+                then do
+                    CL.drop 1
+                    z' <- inner
+                    a <- dropWS
+                    case a of
+                        Just (EventEndElement name')
+                            | name == name' -> CL.drop 1 >> return (Just z')
+                        _ -> lift $ monadThrow $ XML.XmlException ("Expected end tag for: " ++ show name) a
+                else return Nothing
+        _ -> return Nothing
+  where
+    dropWS = do
+        x <- CL.peek
+        let isWS =
+                case x of
+                    Just EventBeginDocument -> True
+                    Just EventEndDocument -> True
+                    Just EventBeginDoctype{} -> True
+                    Just EventEndDoctype -> True
+                    Just EventInstruction{} -> True
+                    Just EventBeginElement{} -> False
+                    Just EventEndElement{} -> False
+                    Just (EventContent (ContentText t))
+                        | T.all isSpace t -> True
+                        | otherwise -> False
+                    Just (EventContent ContentEntity{}) -> False
+                    Just EventComment{} -> True
+                    Just EventCDATA{} -> False
+                    Nothing -> False
+        if isWS then CL.drop 1 >> dropWS else return x
diff --git a/AWS/Lib/Query.hs b/AWS/Lib/Query.hs
--- a/AWS/Lib/Query.hs
+++ b/AWS/Lib/Query.hs
@@ -195,17 +195,17 @@
     urlstr = H.urlEncode True . BASE.encode $ signedStr
 
 checkStatus' ::
-    H.Status -> H.ResponseHeaders -> Maybe SomeException
-checkStatus' = \s@(H.Status sci _) hs ->
+    H.Status -> H.ResponseHeaders -> HTTP.CookieJar -> Maybe SomeException
+checkStatus' = \s@(H.Status sci _) hs cookie ->
     if 200 <= sci && sci < 300 || 400 <= sci
         then Nothing
-        else Just $ toException $ HTTP.StatusCodeException s hs
+        else Just $ toException $ HTTP.StatusCodeException s hs cookie
 
 clientError
     :: (MonadResource m, MonadBaseControl IO m)
     => Int
     -> ResumableSource m ByteString
-    -> (Int -> GLSink Event m a)
+    -> (Int -> Consumer Event m a)
     -> m a
 clientError status rsrc errSink =
     rsrc $$+- XmlP.parseBytes XmlP.def =$ errSink status
@@ -225,7 +225,7 @@
     -> ByteString
     -> [QueryParam]
     -> ByteString
-    -> (ByteString -> Int -> GLSink Event m a)
+    -> (ByteString -> Int -> Consumer Event m a)
     -> m (ResumableSource m ByteString)
 requestQuery cred ctx action params ver errSink = do
     let mgr = manager ctx
@@ -255,7 +255,7 @@
 #endif
 
 #ifdef DEBUG
-conduitLog :: MonadResource m => FilePath -> ByteString -> GInfConduit ByteString m ByteString
+conduitLog :: MonadResource m => FilePath -> ByteString -> Conduit ByteString m ByteString
 conduitLog path url = bracketP (E.try $ IO.openBinaryFile path IO.AppendMode) release go
   where
     release :: Either SomeException IO.Handle -> IO ()
@@ -264,7 +264,7 @@
         liftIO $ BSC.hPutStrLn h ""
         IO.hClose h
 
-    go :: MonadResource m => Either SomeException IO.Handle -> GInfConduit ByteString m ByteString
+    go :: MonadResource m => Either SomeException IO.Handle -> Conduit ByteString m ByteString
     go (Left _) = awaitForever yield
     go (Right h) = do
         liftIO $ do
@@ -278,7 +278,7 @@
     => ByteString -- ^ apiVersion
     -> ByteString -- ^ Action
     -> [QueryParam]
-    -> GLSink Event m a
+    -> Consumer Event m a
     -> AWS AWSContext m a
 commonQuery apiVersion action params sink = do
     ctx <- State.get
diff --git a/AWS/RDS.hs b/AWS/RDS.hs
--- a/AWS/RDS.hs
+++ b/AWS/RDS.hs
@@ -18,6 +18,10 @@
     , module AWS.RDS.DBSubnetGroup
       -- * Event
     , module AWS.RDS.Event
+      -- * EventSubscription
+    , module AWS.RDS.EventSubscription
+      -- * OptionGroup
+    , module AWS.RDS.OptionGroup
     ) where
 
 import Data.Text (Text)
@@ -38,6 +42,8 @@
 import AWS.RDS.DBSnapshot
 import AWS.RDS.DBSubnetGroup
 import AWS.RDS.Event
+import AWS.RDS.EventSubscription
+import AWS.RDS.OptionGroup
 
 initialRDSContext :: HTTP.Manager -> AWSContext
 initialRDSContext mgr = AWSContext
diff --git a/AWS/RDS/DBInstance.hs b/AWS/RDS/DBInstance.hs
--- a/AWS/RDS/DBInstance.hs
+++ b/AWS/RDS/DBInstance.hs
@@ -5,6 +5,8 @@
     , createDBInstance
     , deleteDBInstance
     , createDBInstanceReadReplica
+    , rebootDBInstance
+    , restoreDBInstanceFromDBSnapshot
     ) where
 
 import Data.Text (Text)
@@ -38,17 +40,14 @@
 
 sinkDBInstance
     :: MonadThrow m
-    => GLSink Event m DBInstance
+    => Consumer Event m DBInstance
 sinkDBInstance = DBInstance
     <$> getT "Iops"
     <*> getT "BackupRetentionPeriod"
     <*> getT "DBInstanceStatus"
     <*> getT "MultiAZ"
     <*> elements' "VpcSecurityGroups" "VpcSecurityGroupMembership"
-        (VpcSecurityGroupMembership
-        <$> getT "Status"
-        <*> getT "VpcSecurityGroupId"
-        )
+        vpcSecurityGroupMembershipSink
     <*> getT "DBInstanceIdentifier"
     <*> getT "PreferredBackupWindow"
     <*> getT "PreferredMaintenanceWindow"
@@ -78,11 +77,7 @@
     <*> getT "EngineVersion"
     <*> getT "ReadReplicaSourceDBInstanceIdentifier"
     <*> getT "PubliclyAccessible"
-    <*> elements "DBSecurityGroup"
-        (DBSecurityGroupMembership
-        <$> getT "Status"
-        <*> getT "DBSecurityGroupName"
-        )
+    <*> elements "DBSecurityGroup" dbSecurityGroupMembershipSink
     <*> getT "AutoMinorVersionUpgrade"
     <*> getT "DBName"
     <*> getT "InstanceCreateTime"
@@ -92,7 +87,7 @@
 
 sinkPendingModifiedValues
     :: MonadThrow m
-    => GLSink Event m [PendingModifiedValue]
+    => Consumer Event m [PendingModifiedValue]
 sinkPendingModifiedValues = element "PendingModifiedValues" $
     catMaybes <$> sequence
         [ f PendingModifiedValueMasterUserPassword "MasterUserPassword"
@@ -173,7 +168,7 @@
         [ "SkipFinalSnapshot" |= boolToText True ]
     finalSnapshotParams (FinalSnapshotIdentifier sid) =
         [ "SkipFinalSnapshot" |= boolToText False
-        , "FinalSnapshotIdentifier" |= sid
+        , "FinalDBSnapshotIdentifier" |= sid
         ]
 
 createDBInstanceReadReplica
@@ -190,7 +185,7 @@
         , "AvailabilityZone" |=?
             createReadReplicaAvailabilityZone
         , "DBInstanceClass" |=
-            toText createReadReplicaDBInstanceClass
+            createReadReplicaDBInstanceClass
         , "DBInstanceIdentifier" |=
             createReadReplicaDBInstanceIdentifier
         , "Iops" |=? toText <$> createReadReplicaIops
@@ -200,4 +195,55 @@
             boolToText <$> createReadReplicaPubliclyAccessible
         , "SourceDBInstanceIdentifier" |=
             createReadReplicaSourceDBInstanceIdentifier
+        ]
+
+rebootDBInstance
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ DBInstanceIdentifier
+    -> Maybe Bool -- ^ ForceFailover
+    -> RDS m DBInstance
+rebootDBInstance dbiid force =
+    rdsQuery "RebootDBInstance" params $
+        element "DBInstance" sinkDBInstance
+  where
+    params =
+        [ "DBInstanceIdentifier" |= dbiid
+        , "ForceFailover" |=? boolToText <$> force
+        ]
+
+restoreDBInstanceFromDBSnapshot
+    :: (MonadBaseControl IO m, MonadResource m)
+    => RestoreDBInstanceFromDBSnapshotRequest
+    -> RDS m DBInstance
+restoreDBInstanceFromDBSnapshot RestoreDBInstanceFromDBSnapshotRequest{..} =
+    rdsQuery "RestoreDBInstanceFromDBSnapshot" params $
+        element "DBInstance" sinkDBInstance
+  where
+    params =
+        [ "AutoMinorVersionUpgrade" |=? boolToText <$>
+            restoreDBInstanceFromDBSnapshotRequestAutoMinorVersionUpgrade
+        , "AvailabilityZone" |=?
+            restoreDBInstanceFromDBSnapshotRequestAvailabilityZone
+        , "DBInstanceClass" |=?
+            restoreDBInstanceFromDBSnapshotRequestDBInstanceClass
+        , "DBInstanceIdentifier" |=
+            restoreDBInstanceFromDBSnapshotRequestDBInstanceIdentifier
+        , "DBName" |=? restoreDBInstanceFromDBSnapshotRequestDBName
+        , "DBSnapshotIdentifier" |=
+            restoreDBInstanceFromDBSnapshotRequestDBSnapshotIdentifier
+        , "DBSubnetGroupName" |=?
+            restoreDBInstanceFromDBSnapshotRequestDBSubnetGroupName
+        , "Engine" |=? restoreDBInstanceFromDBSnapshotRequestEngine
+        , "Iops" |=? toText <$>
+            restoreDBInstanceFromDBSnapshotRequestIops
+        , "LicenseModel" |=? toText <$>
+            restoreDBInstanceFromDBSnapshotRequestLicenseModel
+        , "MultiAZ" |=? boolToText <$>
+            restoreDBInstanceFromDBSnapshotRequestMultiAZ
+        , "OptionGroupName" |=?
+            restoreDBInstanceFromDBSnapshotRequestOptionGroupName
+        , "Port" |=? toText <$>
+            restoreDBInstanceFromDBSnapshotRequestPort
+        , "PubliclyAccessible" |=? boolToText <$>
+            restoreDBInstanceFromDBSnapshotRequestPubliclyAccessible
         ]
diff --git a/AWS/RDS/DBParameterGroup.hs b/AWS/RDS/DBParameterGroup.hs
--- a/AWS/RDS/DBParameterGroup.hs
+++ b/AWS/RDS/DBParameterGroup.hs
@@ -7,7 +7,7 @@
     ) where
 
 import Control.Applicative ((<$>), (<*>))
-import Data.Conduit (GLSink, MonadBaseControl, MonadResource, MonadThrow)
+import Data.Conduit (Consumer, MonadBaseControl, MonadResource, MonadThrow)
 import Data.Text (Text)
 import Data.XML.Types (Event)
 
@@ -35,7 +35,7 @@
 
 dbParameterGroupSink
     :: MonadThrow m
-    => GLSink Event m DBParameterGroup
+    => Consumer Event m DBParameterGroup
 dbParameterGroupSink = DBParameterGroup
     <$> getT "DBParameterGroupFamily"
     <*> getT "Description"
diff --git a/AWS/RDS/DBSecurityGroup.hs b/AWS/RDS/DBSecurityGroup.hs
--- a/AWS/RDS/DBSecurityGroup.hs
+++ b/AWS/RDS/DBSecurityGroup.hs
@@ -7,7 +7,7 @@
     ) where
 
 import Control.Applicative ((<$>), (<*>))
-import Data.Conduit (GLSink, MonadBaseControl, MonadResource, MonadThrow)
+import Data.Conduit (Consumer, MonadBaseControl, MonadResource, MonadThrow)
 import Data.Text (Text)
 import Data.XML.Types (Event)
 
@@ -35,13 +35,13 @@
 
 dbSecurityGroupSink
     :: MonadThrow m
-    => GLSink Event m DBSecurityGroup
+    => Consumer Event m DBSecurityGroup
 dbSecurityGroupSink = DBSecurityGroup
     <$> elements "EC2SecurityGroup" (
         EC2SecurityGroup
         <$> getT "Status"
-        <*> getT "EC2SecurityGroupName"
         <*> getT "EC2SecurityGroupOwnerId"
+        <*> getT "EC2SecurityGroupName"
         <*> getT "EC2SecurityGroupId"
         )
     <*> getT "DBSecurityGroupDescription"
diff --git a/AWS/RDS/DBSnapshot.hs b/AWS/RDS/DBSnapshot.hs
--- a/AWS/RDS/DBSnapshot.hs
+++ b/AWS/RDS/DBSnapshot.hs
@@ -4,6 +4,7 @@
     ( describeDBSnapshots
     , createDBSnapshot
     , deleteDBSnapshot
+    , copyDBSnapshot
     ) where
 
 import Data.Text (Text)
@@ -39,12 +40,12 @@
 
 sinkDBSnapshots
     :: MonadThrow m
-    => GLSink Event m [DBSnapshot]
+    => Consumer Event m [DBSnapshot]
 sinkDBSnapshots = elements "DBSnapshot" sinkDBSnapshot
 
 sinkDBSnapshot
     :: MonadThrow m
-    => GLSink Event m DBSnapshot
+    => Consumer Event m DBSnapshot
 sinkDBSnapshot = DBSnapshot
     <$> getT "Port"
     <*> getT "Iops"
@@ -85,3 +86,17 @@
         element "DBSnapshot" sinkDBSnapshot
   where
     params = ["DBSnapshotIdentifier" |= dbsid]
+
+copyDBSnapshot
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ SourceDBSnapshotIdentifier
+    -> Text -- ^ TargetDBSnapshotIdentifier
+    -> RDS m DBSnapshot
+copyDBSnapshot source target =
+    rdsQuery "CopyDBSnapshot" params $
+        element "DBSnapshot" sinkDBSnapshot
+  where
+    params =
+        [ "SourceDBSnapshotIdentifier" |= source
+        , "TargetDBSnapshotIdentifier" |= target
+        ]
diff --git a/AWS/RDS/Event.hs b/AWS/RDS/Event.hs
--- a/AWS/RDS/Event.hs
+++ b/AWS/RDS/Event.hs
@@ -1,6 +1,8 @@
 {-# LANGUAGE FlexibleContexts #-}
+
 module AWS.RDS.Event
     ( describeEvents
+    , describeEventCategories
     ) where
 
 import Control.Applicative ((<$>), (<*>))
@@ -14,6 +16,7 @@
 import AWS.RDS.Internal
 import AWS.RDS.Types
 import AWS.Util (toText)
+import Debug.Trace
 
 describeEvents
     :: (MonadBaseControl IO m, MonadResource m)
@@ -41,18 +44,31 @@
         , "MaxRecords" |=? toText <$> maxRecords
         ]
 
-sourceTypeToText :: SourceType -> Text
-sourceTypeToText SourceTypeDBInstance = "db-instance"
-sourceTypeToText SourceTypeDBParameterGroup = "db-parameter-group"
-sourceTypeToText SourceTypeDBSecurityGroup = "db-security-group"
-sourceTypeToText SourceTypeDBSnapshot = "db-snapshot"
-
 eventSink
     :: MonadThrow m
-    => GLSink XML.Event m Event
+    => Consumer XML.Event m Event
 eventSink = Event
-    <$> getT "Message"
+    <$> do
+        a <- getT "Message"
+        traceShow a $ return a
     <*> getT "SourceType"
-    <*> listConsumer "EventCategories" (getT "EventCategory")
+    <*> elements' "EventCategories" "EventCategory" text
     <*> getT "Date"
     <*> getT "SourceIdentifier"
+
+describeEventCategories
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe SourceType -- ^ SourceType
+    -> RDS m [EventCategoriesMap]
+describeEventCategories stype =
+    rdsQuery "DescribeEventCategories" params $
+        elements' "EventCategoriesMapList" "EventCategoriesMap" eventCategoriesMapSink
+  where
+    params = [ "SourceType" |=? sourceTypeToText <$> stype ]
+
+eventCategoriesMapSink
+    :: MonadThrow m
+    => Consumer XML.Event m EventCategoriesMap
+eventCategoriesMapSink = EventCategoriesMap
+    <$> getT "SourceType"
+    <*> elements' "EventCategories" "EventCategory" text
diff --git a/AWS/RDS/EventSubscription.hs b/AWS/RDS/EventSubscription.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/EventSubscription.hs
@@ -0,0 +1,114 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module AWS.RDS.EventSubscription
+    ( describeEventSubscriptions
+    , createEventSubscription
+    , deleteEventSubscription
+    , modifyEventSubscription
+    , addSourceIdentifierToSubscription
+    ) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.Conduit
+import Data.Text (Text)
+import Data.XML.Types (Event)
+
+import AWS.Lib.Parser
+import AWS.Lib.Query
+import AWS.RDS.Internal
+import AWS.RDS.Types (EventSubscription(..), SourceType)
+import AWS.Util (toText, boolToText)
+
+describeEventSubscriptions
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe Text -- ^ SubscriptionName
+    -> Maybe Text -- ^ Marker
+    -> Maybe Int -- ^ MaxRecords
+    -> RDS m [EventSubscription]
+describeEventSubscriptions name marker maxRecords =
+    rdsQuery "DescribeEventSubscriptions" params $
+        elements' "EventSubscriptionsList" "EventSubscription" eventSubscriptionSink
+  where
+    params =
+        [ "SubscriptionName" |=? name
+        , "Marker" |=? marker
+        , "MaxRecords" |=? toText <$> maxRecords
+        ]
+
+eventSubscriptionSink
+    :: MonadThrow m
+    => Consumer Event m EventSubscription
+eventSubscriptionSink = EventSubscription
+    <$> getT "Enabled"
+    <*> getT "CustomerAwsId"
+    <*> getT "SourceType"
+    <*> getT "Status"
+    <*> elements' "SourceIdsList" "SourceId" text
+    <*> getT "SubscriptionCreationTime"
+    <*> elements' "EventCategoriesList" "EventCategory" text
+    <*> getT "CustSubscriptionId"
+    <*> getT "SnsTopicArn"
+
+createEventSubscription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe Bool -- ^ Enabled
+    -> [Text] -- ^ EventCategories
+    -> Text -- ^ SnsTopicArn
+    -> [Text] -- ^ SourceIds
+    -> Maybe SourceType -- ^ SourceType
+    -> Text -- ^ SubscriptionName
+    -> RDS m EventSubscription
+createEventSubscription enabled ecs topic sids stype name =
+    rdsQuery "CreateEventSubscription" params $
+        element "EventSubscription" eventSubscriptionSink
+  where
+    params =
+        [ "Enabled" |=? boolToText <$> enabled
+        , "EventCategories.member" |.#= ecs
+        , "SnsTopicArn" |= topic
+        , "SourceIds.member" |.#= sids
+        , "SourceType" |=? sourceTypeToText <$> stype
+        , "SubscriptionName" |= name
+        ]
+
+deleteEventSubscription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ SubscriptionName
+    -> RDS m EventSubscription
+deleteEventSubscription name =
+    rdsQuery "DeleteEventSubscription" ["SubscriptionName" |= name] $
+        element "EventSubscription" eventSubscriptionSink
+
+modifyEventSubscription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe Bool -- ^ Enabled
+    -> [Text] -- ^ EventCategories
+    -> Maybe Text -- ^ SnsTopicArn
+    -> Maybe SourceType -- ^ SourceType
+    -> Text -- ^ SubscriptionName
+    -> RDS m EventSubscription
+modifyEventSubscription enabled ecs topic stype name =
+    rdsQuery "ModifyEventSubscription" params $
+        element "EventSubscription" eventSubscriptionSink
+  where
+    params =
+        [ "Enabled" |=? boolToText <$> enabled
+        , "EventCategories.member" |.#= ecs
+        , "SnsTopicArn" |=? topic
+        , "SourceType" |=? sourceTypeToText <$> stype
+        , "SubscriptionName" |= name
+        ]
+
+addSourceIdentifierToSubscription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ SourceIdentifier
+    -> Text -- ^ SubscriptionName
+    -> RDS m EventSubscription
+addSourceIdentifierToSubscription src name =
+    rdsQuery "AddSourceIdentifierToSubscription" params $
+        element "EventSubscription" eventSubscriptionSink
+  where
+    params =
+        [ "SourceIdentifier" |= src
+        , "SubscriptionName" |= name
+        ]
diff --git a/AWS/RDS/Internal.hs b/AWS/RDS/Internal.hs
--- a/AWS/RDS/Internal.hs
+++ b/AWS/RDS/Internal.hs
@@ -8,6 +8,9 @@
     , elements
     , elements'
     , dbSubnetGroupSink
+    , sourceTypeToText
+    , dbSecurityGroupMembershipSink
+    , vpcSecurityGroupMembershipSink
     ) where
 
 import Control.Applicative ((<$>), (<*>))
@@ -25,7 +28,7 @@
 import AWS.Class
 import AWS.Lib.Query
 import AWS.Lib.Parser
-import AWS.RDS.Types (DBSubnetGroup(..), Subnet(..), AvailabilityZone(..))
+import AWS.RDS.Types hiding (Event)
 import AWS.Util
 
 -- | Ver.2013-01-10
@@ -38,7 +41,7 @@
     :: (MonadBaseControl IO m, MonadResource m)
     => ByteString -- ^ Action
     -> [QueryParam]
-    -> GLSink Event m a
+    -> Consumer Event m a
     -> RDS m a
 rdsQuery = commonQuery apiVersion
 
@@ -60,28 +63,28 @@
 sinkResponseOnlyMetadata
     :: MonadThrow m
     => Text
-    -> GLSink Event m RequestId
+    -> Consumer Event m RequestId
 sinkResponseOnlyMetadata action = do
     sinkEventBeginDocument
     element (action <> "Response") $ sinkResponseMetadata
 
 elements :: MonadThrow m
     => Text
-    -> GLSink Event m a
-    -> GLSink Event m [a]
+    -> Consumer Event m a
+    -> Consumer Event m [a]
 elements name = elements' (name <> "s") name
 
 elements' :: forall m a . MonadThrow m
     => Text
     -> Text
-    -> GLSink Event m a
-    -> GLSink Event m [a]
+    -> Consumer Event m a
+    -> Consumer Event m [a]
 elements' setName itemName inner =
     fromMaybe [] <$> elementM setName (listConsumer itemName inner)
 
 dbSubnetGroupSink
     :: MonadThrow m
-    => GLSink Event m DBSubnetGroup
+    => Consumer Event m DBSubnetGroup
 dbSubnetGroupSink = DBSubnetGroup
     <$> getT "VpcId"
     <*> getT "SubnetGroupStatus"
@@ -97,3 +100,23 @@
             <*> getT "ProvisionedIopsCapable"
             )
         )
+
+sourceTypeToText :: SourceType -> Text
+sourceTypeToText SourceTypeDBInstance = "db-instance"
+sourceTypeToText SourceTypeDBParameterGroup = "db-parameter-group"
+sourceTypeToText SourceTypeDBSecurityGroup = "db-security-group"
+sourceTypeToText SourceTypeDBSnapshot = "db-snapshot"
+
+dbSecurityGroupMembershipSink
+    :: MonadThrow m
+    => Consumer Event m DBSecurityGroupMembership
+dbSecurityGroupMembershipSink = DBSecurityGroupMembership
+    <$> getT "Status"
+    <*> getT "DBSecurityGroupName"
+
+vpcSecurityGroupMembershipSink
+    :: MonadThrow m
+    => Consumer Event m VpcSecurityGroupMembership
+vpcSecurityGroupMembershipSink = VpcSecurityGroupMembership
+    <$> getT "Status"
+    <*> getT "VpcSecurityGroupId"
diff --git a/AWS/RDS/OptionGroup.hs b/AWS/RDS/OptionGroup.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/OptionGroup.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module AWS.RDS.OptionGroup
+    ( describeOptionGroups
+    , createOptionGroup
+    , deleteOptionGroup
+    ) where
+
+import Control.Applicative ((<$>), (<*>))
+import Data.Conduit
+import Data.Text (Text)
+import Data.XML.Types (Event)
+
+import AWS.Lib.Parser
+import AWS.Lib.Query
+import AWS.RDS.Internal
+import AWS.RDS.Types (OptionGroup(..), Option(..))
+import AWS.Util (toText)
+
+describeOptionGroups
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe Text -- ^ EngineName
+    -> Maybe Text -- ^ MajorEngineVersion
+    -> Maybe Text -- ^ Marker
+    -> Maybe Int -- ^ MaxRecords
+    -> Maybe Text -- ^ OptionGroupName
+    -> RDS m [OptionGroup]
+describeOptionGroups engine ver marker maxRecords name =
+    rdsQuery "DescribeOptionGroups" params $
+        elements' "OptionGroupsList" "OptionGroup" optionGroupSink
+  where
+    params =
+        [ "EngineName" |=? engine
+        , "MajorEngineVersion" |=? ver
+        , "Marker" |=? marker
+        , "MaxRecords" |=? toText <$> maxRecords
+        , "OptionGroupName" |=? name
+        ]
+
+optionGroupSink
+    :: MonadThrow m
+    => Consumer Event m OptionGroup
+optionGroupSink = OptionGroup
+    <$> getT "AllowsVpcAndNonVpcInstanceMemberships"
+    <*> getT "MajorEngineVersion"
+    <*> getT "OptionGroupName"
+    <*> getT "VpcId"
+    <*> getT "EngineName"
+    <*> getT "OptionGroupDescription"
+    <*> elements "Option" optionSink
+
+optionSink
+    :: MonadThrow m
+    => Consumer Event m Option
+optionSink = Option
+    <$> getT "Port"
+    <*> getT "OptionName"
+    <*> getT "OptionDescription"
+    <*> elements "VpcSecurityGroupMembership" vpcSecurityGroupMembershipSink
+    <*> elements' "DBSecurityGroupMemberships" "DBSecurityGroup"
+        dbSecurityGroupMembershipSink
+
+createOptionGroup
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ EngineName
+    -> Text -- ^ MajorEngineVersion
+    -> Text -- ^ OptionGroupDescription
+    -> Text -- ^ OptionGroupName
+    -> RDS m OptionGroup
+createOptionGroup engine ver desc name =
+    rdsQuery "CreateOptionGroup" params $
+        element "OptionGroup" optionGroupSink
+  where
+    params =
+        [ "EngineName" |= engine
+        , "MajorEngineVersion" |= ver
+        , "OptionGroupDescription" |= desc
+        , "OptionGroupName" |= name
+        ]
+
+deleteOptionGroup
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ OptionGroupName
+    -> RDS m ()
+deleteOptionGroup name =
+    rdsQueryOnlyMetadata "DeleteOptionGroup"
+        [ "OptionGroupName" |= name ]
diff --git a/AWS/RDS/Types.hs b/AWS/RDS/Types.hs
--- a/AWS/RDS/Types.hs
+++ b/AWS/RDS/Types.hs
@@ -11,6 +11,10 @@
     , module AWS.RDS.Types.DBSubnetGroup
       -- * Event
     , module AWS.RDS.Types.Event
+      -- * EventSubscription
+    , module AWS.RDS.Types.EventSubscription
+      -- * OptionGroup
+    , module AWS.RDS.Types.OptionGroup
     ) where
 
 import AWS.RDS.Types.DBInstance
@@ -19,3 +23,5 @@
 import AWS.RDS.Types.DBSnapshot
 import AWS.RDS.Types.DBSubnetGroup
 import AWS.RDS.Types.Event
+import AWS.RDS.Types.EventSubscription
+import AWS.RDS.Types.OptionGroup
diff --git a/AWS/RDS/Types/DBInstance.hs b/AWS/RDS/Types/DBInstance.hs
--- a/AWS/RDS/Types/DBInstance.hs
+++ b/AWS/RDS/Types/DBInstance.hs
@@ -14,6 +14,7 @@
     , LicenseModel(..)
     , FinalSnapshot(..)
     , CreateReadReplicaRequest(..)
+    , RestoreDBInstanceFromDBSnapshotRequest(..)
     ) where
 
 import AWS.Lib.FromText (Text, UTCTime, deriveFromText)
@@ -72,13 +73,13 @@
 
 data Endpoint = Endpoint
     { endpointPort :: Int
-    , endpointAddress :: Text
+    , endpointAddress :: Maybe Text
     }
   deriving (Show, Eq)
 
 data OptionGroupMembership = OptionGroupMembership
-    { optionGroupName :: Text
-    , optionGroupStatus :: Text
+    { optionGroupMembershipName :: Text
+    , optionGroupMembershipStatus :: Text
     }
   deriving (Show, Eq)
 
@@ -156,6 +157,39 @@
     , createReadReplicaPubliclyAccessible :: Maybe Bool
     , createReadReplicaSourceDBInstanceIdentifier :: Text
     }
+  deriving (Show, Eq)
+
+data RestoreDBInstanceFromDBSnapshotRequest
+    = RestoreDBInstanceFromDBSnapshotRequest
+        { restoreDBInstanceFromDBSnapshotRequestAutoMinorVersionUpgrade
+            :: Maybe Bool
+        , restoreDBInstanceFromDBSnapshotRequestAvailabilityZone
+            :: Maybe Text
+        , restoreDBInstanceFromDBSnapshotRequestDBInstanceClass
+            :: Maybe DBInstanceClass
+        , restoreDBInstanceFromDBSnapshotRequestDBInstanceIdentifier
+            :: Text
+        , restoreDBInstanceFromDBSnapshotRequestDBName
+            :: Maybe Text
+        , restoreDBInstanceFromDBSnapshotRequestDBSnapshotIdentifier
+            :: Text
+        , restoreDBInstanceFromDBSnapshotRequestDBSubnetGroupName
+            :: Maybe Text
+        , restoreDBInstanceFromDBSnapshotRequestEngine
+            :: Maybe Engine
+        , restoreDBInstanceFromDBSnapshotRequestIops
+            :: Maybe Int
+        , restoreDBInstanceFromDBSnapshotRequestLicenseModel
+            :: Maybe LicenseModel
+        , restoreDBInstanceFromDBSnapshotRequestMultiAZ
+            :: Maybe Bool
+        , restoreDBInstanceFromDBSnapshotRequestOptionGroupName
+            :: Maybe Text
+        , restoreDBInstanceFromDBSnapshotRequestPort
+            :: Maybe Int
+        , restoreDBInstanceFromDBSnapshotRequestPubliclyAccessible
+            :: Maybe Bool
+        }
   deriving (Show, Eq)
 
 deriveFromText "LicenseModel"
diff --git a/AWS/RDS/Types/DBSecurityGroup.hs b/AWS/RDS/Types/DBSecurityGroup.hs
--- a/AWS/RDS/Types/DBSecurityGroup.hs
+++ b/AWS/RDS/Types/DBSecurityGroup.hs
@@ -22,8 +22,8 @@
 
 data EC2SecurityGroup = EC2SecurityGroup
     { ec2SecurityGroupStatus :: EC2SecurityGroupStatus
-    , ec2SecurityGroupName :: Text
     , ec2SecurityGroupOwnerId :: Maybe Text
+    , ec2SecurityGroupName :: Text
     , ec2SecurityGroupId :: Maybe Text
     }
   deriving (Show, Eq)
diff --git a/AWS/RDS/Types/Event.hs b/AWS/RDS/Types/Event.hs
--- a/AWS/RDS/Types/Event.hs
+++ b/AWS/RDS/Types/Event.hs
@@ -3,6 +3,7 @@
 module AWS.RDS.Types.Event
     ( Event(..)
     , SourceType(..)
+    , EventCategoriesMap(..)
     ) where
 
 import AWS.Lib.FromText (deriveFromText, Text, UTCTime)
@@ -22,6 +23,12 @@
     | SourceTypeDBSecurityGroup
     | SourceTypeDBSnapshot
   deriving (Show, Read, Eq)
+
+data EventCategoriesMap = EventCategoriesMap
+    { eventCategoriesMapSourceType :: SourceType
+    , eventCategoriesMapEventCategories :: [Text]
+    }
+  deriving (Show, Eq)
 
 deriveFromText "SourceType"
     ["db-instance", "db-parameter-group", "db-security-group", "db-snapshot"]
diff --git a/AWS/RDS/Types/EventSubscription.hs b/AWS/RDS/Types/EventSubscription.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/Types/EventSubscription.hs
@@ -0,0 +1,39 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module AWS.RDS.Types.EventSubscription
+    ( EventSubscription(..)
+    ) where
+
+import AWS.Lib.FromText (deriveFromText, Text)
+import AWS.RDS.Types.Event (SourceType)
+
+data EventSubscription = EventSubscription
+    { eventSubscriptionEnabled :: Bool
+    , eventSubscriptionCustomerAwsId :: Text
+    , eventSubscriptionSourceType :: Maybe SourceType
+    , eventSubscriptionStatus :: EventSubscriptionStatus
+    , eventSubscriptionSourceIds :: [Text]
+    , eventSubscriptionCreationTime :: Text
+    , eventSubscriptionEventCategories :: [Text]
+    , eventSubscriptionCustSubscriptionId :: Text
+    , eventSubscriptionSnsTopicArn :: Text
+    }
+  deriving (Show, Eq)
+
+data EventSubscriptionStatus
+    = EventSubscriptionStatusCreating
+    | EventSubscriptionStatusModifying
+    | EventSubscriptionStatusDeleting
+    | EventSubscriptionStatusActive
+    | EventSubscriptionStatusNoPermission
+    | EventSubscriptionStatusTopicNotExist
+  deriving (Show, Read, Eq)
+
+deriveFromText "EventSubscriptionStatus"
+    [ "creating"
+    , "modifying"
+    , "deleting"
+    , "active"
+    , "no-permission"
+    , "topic-not-exist"
+    ]
diff --git a/AWS/RDS/Types/OptionGroup.hs b/AWS/RDS/Types/OptionGroup.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/Types/OptionGroup.hs
@@ -0,0 +1,30 @@
+module AWS.RDS.Types.OptionGroup
+    ( OptionGroup(..)
+    , Option(..)
+    ) where
+
+import AWS.Lib.FromText (Text)
+import AWS.RDS.Types.DBInstance
+    ( VpcSecurityGroupMembership
+    , DBSecurityGroupMembership
+    )
+
+data OptionGroup = OptionGroup
+    { optionGroupAllowsVpcAndNonVpcInstanceMemberships :: Bool
+    , optionGroupMajorEngineVersion :: Text
+    , optionGroupName :: Text
+    , optionGroupVpcId :: Maybe Text
+    , optionGroupEngineName :: Text
+    , optionGroupDescription :: Text
+    , optionGroupOption :: [Option]
+    }
+  deriving (Show, Eq)
+
+data Option = Option
+    { optionPort :: Int
+    , optionName :: Text
+    , optionDescription :: Text
+    , optionVpcSecurityGroupMemberships :: [VpcSecurityGroupMembership]
+    , optionDBSecurityGroupMemberships :: [DBSecurityGroupMembership]
+    }
+  deriving (Show, Eq)
diff --git a/AWS/RDS/Util.hs b/AWS/RDS/Util.hs
--- a/AWS/RDS/Util.hs
+++ b/AWS/RDS/Util.hs
@@ -54,7 +54,7 @@
     passwd
     (dbInstanceMasterUsername db)
     (Just $ dbInstanceMultiAZ db)
-    (optionGroupName <$> dbInstanceOptionGroupMembership db)
+    (optionGroupMembershipName <$> dbInstanceOptionGroupMembership db)
     (endpointPort <$> dbInstanceEndpoint db)
     (Just $ dbInstancePreferredBackupWindow db)
     (Just $ dbInstancePreferredMaintenanceWindow db)
diff --git a/aws-sdk.cabal b/aws-sdk.cabal
--- a/aws-sdk.cabal
+++ b/aws-sdk.cabal
@@ -1,5 +1,5 @@
 name:                aws-sdk
-version:             0.11.3.3
+version:             0.12.0
 synopsis:            AWS SDK for Haskell
 description: AWS (Amazon Web Services) sdk for Haskell.
              .
@@ -94,12 +94,16 @@
                    , AWS.RDS.DBSnapshot
                    , AWS.RDS.DBSubnetGroup
                    , AWS.RDS.Event
+                   , AWS.RDS.EventSubscription
+                   , AWS.RDS.OptionGroup
                    , AWS.RDS.Types.DBInstance
                    , AWS.RDS.Types.DBParameterGroup
                    , AWS.RDS.Types.DBSecurityGroup
                    , AWS.RDS.Types.DBSnapshot
                    , AWS.RDS.Types.DBSubnetGroup
                    , AWS.RDS.Types.Event
+                   , AWS.RDS.Types.EventSubscription
+                   , AWS.RDS.Types.OptionGroup
                    , AWS.ELB.Internal
                    , AWS.ELB.LoadBalancer
                    , AWS.CloudWatch.Internal
@@ -117,11 +121,11 @@
                    , base64-bytestring >= 1.0.0.0
                    , bytestring
                    , http-types
-                   , conduit >= 0.5.3 && < 1.0.0
+                   , conduit >= 1.0.0
                    , transformers
                    , time
                    , old-locale
-                   , http-conduit < 1.9.0
+                   , http-conduit >= 1.9.0
                    , data-default
                    , xml-conduit >= 1.0.3.3
                    , xml-types
@@ -153,15 +157,15 @@
                  , text
                  , monad-control
                  , transformers
-                 , http-conduit
+                 , http-conduit >= 1.9.0
                  , hspec
                  , QuickCheck
-                 , hspec
                  , HUnit
                  , lifted-base
                  , iproute
                  , tls
                  , time
+                 , random
 
 source-repository head
     type:            git
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -23,7 +23,6 @@
     runRouteTests
     runRouteTableTests
     runRegionTests
-    runInstanceTests
     runAvailabilityZoneTests
     runTagTests
     runKeyPairTests
@@ -34,12 +33,14 @@
     runAclTests
 
     -- RDS Tests
+    runDBSnapshotTests
     runDBInstanceTests
     runDBParameterGroupTests
     runDBSecurityGroupTests
-    runDBSnapshotTests
     runDBSubnetGroupTests
     runEventTests
+    runEventSubscriptionTests
+    runOptionGroupTests
 
     -- ELB Tests
     runLoadBalancerTests
