diff --git a/AWS/CloudWatch.hs b/AWS/CloudWatch.hs
--- a/AWS/CloudWatch.hs
+++ b/AWS/CloudWatch.hs
@@ -12,7 +12,6 @@
 
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Monad.IO.Class (MonadIO)
 import qualified Control.Monad.State as State
 import qualified Network.HTTP.Conduit as HTTP
diff --git a/AWS/CloudWatch/Internal.hs b/AWS/CloudWatch/Internal.hs
--- a/AWS/CloudWatch/Internal.hs
+++ b/AWS/CloudWatch/Internal.hs
@@ -6,7 +6,6 @@
 import Data.ByteString (ByteString)
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.Monoid ((<>))
 import Data.XML.Types (Event(..))
 
diff --git a/AWS/CloudWatch/Metric.hs b/AWS/CloudWatch/Metric.hs
--- a/AWS/CloudWatch/Metric.hs
+++ b/AWS/CloudWatch/Metric.hs
@@ -8,7 +8,6 @@
 import Data.Text (Text)
 import Data.Time (UTCTime)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.Util
diff --git a/AWS/EC2.hs b/AWS/EC2.hs
--- a/AWS/EC2.hs
+++ b/AWS/EC2.hs
@@ -23,6 +23,7 @@
     , module AWS.EC2.SecurityGroup
       -- * NetworkInterface
     , module AWS.EC2.NetworkInterface
+    , module AWS.EC2.NetworkInterfaceAttribute
       -- * Placements
     , module AWS.EC2.Region
     , module AWS.EC2.AvailabilityZone
@@ -33,10 +34,10 @@
     , module AWS.EC2.Subnets
     , module AWS.EC2.Acl
     , module AWS.EC2.RouteTable
+    , module AWS.EC2.Route
     ) where
 
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import qualified Control.Monad.State as State
 import Data.Text (Text)
 import Data.ByteString (ByteString)
@@ -60,8 +61,10 @@
 import AWS.EC2.VPC
 import AWS.EC2.Subnets
 import AWS.EC2.Acl
+import AWS.EC2.Route
 import AWS.EC2.RouteTable
 import AWS.EC2.NetworkInterface
+import AWS.EC2.NetworkInterfaceAttribute
 
 -- | set endpoint to EC2 context by giving the EC2 region.
 setRegion
diff --git a/AWS/EC2/Acl.hs b/AWS/EC2/Acl.hs
--- a/AWS/EC2/Acl.hs
+++ b/AWS/EC2/Acl.hs
@@ -13,7 +13,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Address.hs b/AWS/EC2/Address.hs
--- a/AWS/EC2/Address.hs
+++ b/AWS/EC2/Address.hs
@@ -14,7 +14,6 @@
 import Data.IP (IPv4)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/AvailabilityZone.hs b/AWS/EC2/AvailabilityZone.hs
--- a/AWS/EC2/AvailabilityZone.hs
+++ b/AWS/EC2/AvailabilityZone.hs
@@ -8,7 +8,6 @@
 
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Image.hs b/AWS/EC2/Image.hs
--- a/AWS/EC2/Image.hs
+++ b/AWS/EC2/Image.hs
@@ -12,7 +12,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 import Control.Monad (join)
 
diff --git a/AWS/EC2/Instance.hs b/AWS/EC2/Instance.hs
--- a/AWS/EC2/Instance.hs
+++ b/AWS/EC2/Instance.hs
@@ -19,7 +19,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 import Data.Maybe (fromMaybe, fromJust)
 import qualified Data.Map as Map
diff --git a/AWS/EC2/Internal.hs b/AWS/EC2/Internal.hs
--- a/AWS/EC2/Internal.hs
+++ b/AWS/EC2/Internal.hs
@@ -13,6 +13,7 @@
     , stateReasonSink
     , volumeTypeSink
     , groupSetSink
+    , networkInterfaceAttachmentSink
     ) where
 
 import Control.Monad.IO.Class (MonadIO)
@@ -89,3 +90,16 @@
 groupSetSink = itemsSet "groupSet" $ Group
     <$> getT "groupId"
     <*> getT "groupName"
+
+networkInterfaceAttachmentSink
+    :: MonadThrow m
+    => GLSink Event m (Maybe NetworkInterfaceAttachment)
+networkInterfaceAttachmentSink = elementM "attachment" $
+    NetworkInterfaceAttachment
+    <$> getT "attachmentId"
+    <*> getT "instanceId"
+    <*> getT "instanceOwnerId"
+    <*> getT "deviceIndex"
+    <*> getT "status"
+    <*> getT "attachTime"
+    <*> getT "deleteOnTermination"
diff --git a/AWS/EC2/KeyPair.hs b/AWS/EC2/KeyPair.hs
--- a/AWS/EC2/KeyPair.hs
+++ b/AWS/EC2/KeyPair.hs
@@ -11,7 +11,6 @@
 
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/NetworkInterface.hs b/AWS/EC2/NetworkInterface.hs
--- a/AWS/EC2/NetworkInterface.hs
+++ b/AWS/EC2/NetworkInterface.hs
@@ -4,13 +4,16 @@
     ( assignPrivateIpAddresses
     , unassignPrivateIpAddresses
     , describeNetworkInterfaces
+    , createNetworkInterface
+    , deleteNetworkInterface
+    , attachNetworkInterface
+    , detachNetworkInterface
     ) where
 
 import Data.IP (IPv4)
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
@@ -82,15 +85,7 @@
     <*> getT "privateDnsName"
     <*> getT "sourceDestCheck"
     <*> groupSetSink
-    <*> elementM "attachment" (NetworkInterfaceAttachment
-        <$> getT "attachmentId"
-        <*> getT "instanceId"
-        <*> getT "instanceOwnerId"
-        <*> getT "deviceIndex"
-        <*> getT "status"
-        <*> getT "attachTime"
-        <*> getT "deleteOnTermination"
-        )
+    <*> networkInterfaceAttachmentSink
     <*> networkInterfaceAssociationSink
     <*> resourceTagSink
     <*> itemsSet "privateIpAddressesSet" (
@@ -112,3 +107,66 @@
         <*> getT "publicDnsName"
         <*> getT "ipOwnerId"
         <*> getT "associationId"
+
+createNetworkInterface
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the subnet to associate with the network interface.
+    -> SecondaryPrivateIpAddressParam -- ^ The private IP address of the specified network interface.
+    -> Maybe Text -- ^ The description of the network interface.
+    -> [Text] -- ^ A list of security group IDs for use by the network interface.
+    -> EC2 m NetworkInterface
+createNetworkInterface subnet privateAddresses description securityGroupIds =
+    ec2Query "CreateNetworkInterface" params $ element "networkInterface" networkInterfaceSink
+  where
+    params :: [QueryParam]
+    params =
+        [ "SubnetId" |= subnet
+        , "Description" |=? description
+        , "SecurityGroup" |.#= securityGroupIds
+        ] ++ fromSecondary privateAddresses
+
+    fromSecondary :: SecondaryPrivateIpAddressParam -> [QueryParam]
+    fromSecondary SecondaryPrivateIpAddressParamNothing = []
+    fromSecondary (SecondaryPrivateIpAddressParamCount n) = ["SecondaryPrivateIpAddressCount" |= toText n]
+    fromSecondary (SecondaryPrivateIpAddressParamSpecified addrs primary) =
+        [ "PrivateIpAddresses" |.#. map (\addr -> ["PrivateIpAddress" |= toText addr]) addrs
+        , maybeParam $ primaryParam <$> primary
+        ]
+
+    primaryParam :: Int -> QueryParam
+    primaryParam n = "PrivateIpAddresses" |.+ toText n |.+ "Primary" |= "true"
+
+deleteNetworkInterface
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m Bool
+deleteNetworkInterface networkInterface =
+    ec2Query "DeleteNetworkInterface" ["NetworkInterfaceId" |= networkInterface] $ getT "return"
+
+attachNetworkInterface
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface to attach.
+    -> Text -- ^ The ID of the instance to attach to the network interface.
+    -> Int -- ^ The index of the device for the network interface attachment.
+    -> EC2 m Text -- ^ The ID of the attachment.
+attachNetworkInterface networkInterface inst deviceIdx =
+    ec2Query "AttachNetworkInterface" params $ getT "attachmentId"
+  where
+    params =
+        [ "NetworkInterfaceId" |= networkInterface
+        , "InstanceId" |= inst
+        , "DeviceIndex" |= toText deviceIdx
+        ]
+
+detachNetworkInterface
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the attachment.
+    -> Maybe Bool -- ^ Set to true to force a detachment.
+    -> EC2 m Bool
+detachNetworkInterface attachment force =
+    ec2Query "DetachNetworkInterface" params $ getT "return"
+  where
+    params =
+        [ "AttachmentId" |= attachment
+        , "Force" |=? toText <$> force
+        ]
diff --git a/AWS/EC2/NetworkInterfaceAttribute.hs b/AWS/EC2/NetworkInterfaceAttribute.hs
new file mode 100644
--- /dev/null
+++ b/AWS/EC2/NetworkInterfaceAttribute.hs
@@ -0,0 +1,130 @@
+{-# LANGUAGE FlexibleContexts, Rank2Types #-}
+module AWS.EC2.NetworkInterfaceAttribute
+   ( describeNetworkInterfaceDescription
+   , describeNetworkInterfaceGroupSet
+   , describeNetworkInterfaceSourceDestCheck
+   , describeNetworkInterfaceAttachment
+   , modifyNetworkInterfaceDescription
+   , modifyNetworkInterfaceSecurityGroup
+   , modifyNetworkInterfaceSourceDestCheck
+   , modifyNetworkInterfaceAttachment
+   , resetNetworkInterfaceSourceDestCheck
+   ) where
+
+import Data.Text (Text)
+import Data.Conduit (GLSink, MonadBaseControl, MonadResource)
+import Data.XML.Types (Event)
+
+import AWS.EC2.Internal (EC2, groupSetSink, networkInterfaceAttachmentSink)
+import AWS.EC2.Query
+import AWS.EC2.Types (Group, NetworkInterfaceAttachment(..))
+import AWS.Lib.Parser (element, getT, getT_)
+import AWS.Util (toText)
+
+describeNetworkInterfaceDescription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m Text
+describeNetworkInterfaceDescription = describeNetworkInterfaceAttribute "description" $
+  element "description" $ getT "value"
+
+describeNetworkInterfaceGroupSet
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m [Group]
+describeNetworkInterfaceGroupSet = describeNetworkInterfaceAttribute "groupSet" groupSetSink
+
+describeNetworkInterfaceSourceDestCheck
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m Bool
+describeNetworkInterfaceSourceDestCheck = describeNetworkInterfaceAttribute "sourceDestCheck" $
+  element "sourceDestCheck" $ getT "value"
+
+describeNetworkInterfaceAttachment
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m (Maybe NetworkInterfaceAttachment)
+describeNetworkInterfaceAttachment = describeNetworkInterfaceAttribute "attachment" networkInterfaceAttachmentSink
+
+describeNetworkInterfaceAttribute
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text
+    -> GLSink Event m a
+    -> Text
+    -> EC2 m a
+describeNetworkInterfaceAttribute action sink networkInterface =
+    ec2Query "DescribeNetworkInterfaceAttribute" params $
+        getT_ "networkInterfaceId" >> sink
+  where
+    params =
+        [ "NetworkInterfaceId" |= networkInterface
+        , "Attribute" |= action
+        ]
+
+modifyNetworkInterfaceDescription
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> Text -- ^ The description of the network interface.
+    -> EC2 m Bool
+modifyNetworkInterfaceDescription iface desc =
+    modifyNetworkInterfaceAttribute iface ["Description.Value" |= desc]
+
+modifyNetworkInterfaceSecurityGroup
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> [Text] -- ^ The security group ids that a network interface is in.
+    -> EC2 m Bool
+modifyNetworkInterfaceSecurityGroup iface groups =
+    modifyNetworkInterfaceAttribute iface ["SecurityGroupId" |.#= groups]
+
+modifyNetworkInterfaceSourceDestCheck
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> Bool -- ^ Enables a Network Address Translation (NAT) instance in a VPC to perform NAT.
+    -> EC2 m Bool
+modifyNetworkInterfaceSourceDestCheck iface check =
+    modifyNetworkInterfaceAttribute iface ["SourceDestCheck.Value" |= toText check]
+
+modifyNetworkInterfaceAttachment
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> Text -- ^ The ID of the interface attachment.
+    -> Bool -- ^ Specifies whether to delete the attachment when terminating the instance.
+    -> EC2 m Bool
+modifyNetworkInterfaceAttachment iface attachment deleteOnTermination =
+    modifyNetworkInterfaceAttribute iface params
+  where
+    params =
+        [ "Attachment.AttachmentId" |= attachment
+        , "Attachment.DeleteOnTermination" |= toText deleteOnTermination
+        ]
+
+modifyNetworkInterfaceAttribute
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text
+    -> [QueryParam]
+    -> EC2 m Bool
+modifyNetworkInterfaceAttribute iface params =
+    ec2Query "ModifyNetworkInterfaceAttribute" params' $ getT "return"
+  where
+    params' = ("NetworkInterfaceId" |= iface) : params
+
+resetNetworkInterfaceSourceDestCheck
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ The ID of the network interface.
+    -> EC2 m Bool
+resetNetworkInterfaceSourceDestCheck = resetNetworkInterfaceAttribute "sourceDestCheck"
+
+resetNetworkInterfaceAttribute
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text
+    -> Text
+    -> EC2 m Bool
+resetNetworkInterfaceAttribute attrName iface =
+    ec2Query "ResetNetworkInterfaceAttribute" params $ getT "return"
+  where
+    params =
+        [ "NetworkInterfaceId" |= iface
+        , "Attribute" |= attrName
+        ]
diff --git a/AWS/EC2/Query.hs b/AWS/EC2/Query.hs
--- a/AWS/EC2/Query.hs
+++ b/AWS/EC2/Query.hs
@@ -18,7 +18,6 @@
 import Data.XML.Types (Event(..))
 import Data.Conduit
 import qualified Data.Conduit.List as CL
-import Control.Monad.Trans.Control (MonadBaseControl)
 import qualified Text.XML.Stream.Parse as XmlP
 import Control.Monad.Trans.Class (lift)
 import Control.Monad.IO.Class (MonadIO)
@@ -114,14 +113,7 @@
     => ByteString
     -> [QueryParam]
     -> EC2 m a
-ec2QueryDebug action params = do
-    cred <- Reader.ask
-    ctx <- State.get
-    lift $ do
-        liftIO $ mapM_ print params
-        response <- requestQuery cred ctx action params apiVersion sinkError
-        (res, _) <- unwrapResumable response
-        res $$ CB.sinkFile "debug.txt" >>= fail "debug"
+ec2QueryDebug = debugQuery apiVersion
 #endif
 
 ec2Delete
diff --git a/AWS/EC2/Region.hs b/AWS/EC2/Region.hs
--- a/AWS/EC2/Region.hs
+++ b/AWS/EC2/Region.hs
@@ -8,7 +8,6 @@
 
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Route.hs b/AWS/EC2/Route.hs
new file mode 100644
--- /dev/null
+++ b/AWS/EC2/Route.hs
@@ -0,0 +1,68 @@
+{-# LANGUAGE FlexibleContexts, RecordWildCards #-}
+module AWS.EC2.Route
+    ( createRoute
+    , deleteRoute
+    , replaceRoute
+    ) where
+
+import Data.ByteString (ByteString)
+import Data.Conduit (MonadBaseControl, MonadResource)
+import Data.IP (AddrRange, IPv4)
+import Data.Text (Text)
+
+import AWS.EC2.Internal (EC2)
+import AWS.EC2.Query (ec2Query, (|=))
+import AWS.EC2.Types (CreateRouteRequest(..))
+import AWS.Lib.Parser (getT)
+import AWS.Util (toText)
+
+createRoute
+    :: (MonadResource m, MonadBaseControl IO m)
+    => CreateRouteRequest
+    -> EC2 m Bool
+createRoute = routeRequest "CreateRoute"
+
+deleteRoute
+    :: (MonadResource m, MonadBaseControl IO m)
+    => Text -- ^ The ID of the route table.
+    -> AddrRange IPv4 -- ^ The CIDR range of the destination for the route to delete.
+    -> EC2 m Bool
+deleteRoute tableId cidrBlock =
+    ec2Query "DeleteRoute"
+        [ "RouteTableId" |= tableId
+        , "DestinationCidrBlock" |= toText cidrBlock
+        ] $ getT "return"
+
+replaceRoute
+    :: (MonadResource m, MonadBaseControl IO m)
+    => CreateRouteRequest
+    -> EC2 m Bool
+replaceRoute = routeRequest "ReplaceRoute"
+
+routeRequest
+    :: (MonadResource m, MonadBaseControl IO m)
+    => ByteString
+    -> CreateRouteRequest
+    -> EC2 m Bool
+routeRequest action (CreateRouteToGateway{..}) =
+      routeRequest' action createRouteTableId createRouteDestinationCidrBlock "GatewayId" createRouteGatewayId
+routeRequest action (CreateRouteToInstance{..}) =
+      routeRequest' action createRouteTableId createRouteDestinationCidrBlock "InstanceId" createRouteInstanceId
+routeRequest action (CreateRouteToNetworkInterface{..}) =
+      routeRequest' action createRouteTableId createRouteDestinationCidrBlock "NetworkInterfaceId" createRouteNetworkInterfaceId
+
+routeRequest'
+    :: (MonadResource m, MonadBaseControl IO m)
+    => ByteString
+    -> Text
+    -> AddrRange IPv4
+    -> Text
+    -> Text
+    -> EC2 m Bool
+routeRequest' action tableId cidrBlock targetName targetId =
+    ec2Query action
+        [ "RouteTableId" |= tableId
+        , "DestinationCidrBlock" |= toText cidrBlock
+        , targetName |= targetId
+        ] $ getT "return"
+
diff --git a/AWS/EC2/RouteTable.hs b/AWS/EC2/RouteTable.hs
--- a/AWS/EC2/RouteTable.hs
+++ b/AWS/EC2/RouteTable.hs
@@ -12,7 +12,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/SecurityGroup.hs b/AWS/EC2/SecurityGroup.hs
--- a/AWS/EC2/SecurityGroup.hs
+++ b/AWS/EC2/SecurityGroup.hs
@@ -15,7 +15,6 @@
 
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Snapshot.hs b/AWS/EC2/Snapshot.hs
--- a/AWS/EC2/Snapshot.hs
+++ b/AWS/EC2/Snapshot.hs
@@ -13,7 +13,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Subnets.hs b/AWS/EC2/Subnets.hs
--- a/AWS/EC2/Subnets.hs
+++ b/AWS/EC2/Subnets.hs
@@ -9,7 +9,6 @@
 import Data.Text (Text)
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Tag.hs b/AWS/EC2/Tag.hs
--- a/AWS/EC2/Tag.hs
+++ b/AWS/EC2/Tag.hs
@@ -8,7 +8,6 @@
 
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/EC2/Types.hs b/AWS/EC2/Types.hs
--- a/AWS/EC2/Types.hs
+++ b/AWS/EC2/Types.hs
@@ -16,6 +16,7 @@
     , BlockDeviceMapping(..)
     , BlockDeviceMappingParam(..)
     , ConsoleOutput(..)
+    , CreateRouteRequest(..)
     , CreateSubnetRequest(..)
     , CreateVolumePermission(..)
     , CreateVolumePermissionItem(..)
@@ -456,9 +457,9 @@
     , instanceNetworkInterfaceOwnerId :: Text
     , instanceNetworkInterfaceStatus :: Text
     , instanceNetworkInterfaceMacAddress :: Maybe Text
-    , instanceNetworkInterfacePrivateIpAddress :: IPv4
+    , instanceNetworkInterfacePrivateIpAddress :: Maybe IPv4
     , instanceNetworkInterfacePrivateDnsName :: Maybe Text
-    , instanceNetworkInterfaceSourceDestCheck :: Bool
+    , instanceNetworkInterfaceSourceDestCheck :: Maybe Bool
     , instanceNetworkInterfaceGroupSet :: [Group]
     , instanceNetworkInterfaceAttachment
         :: InstanceNetworkInterfaceAttachment
@@ -755,8 +756,8 @@
 data VpnConnection = VpnConnection
     { vpnConnectionId :: Text
     , vpnConnectionState :: VpnConnectionState
-    , vpnConnectionCustomerGatewayConfiguration :: Text
-    , vpnConnectionType :: Text
+    , vpnConnectionCustomerGatewayConfiguration :: Maybe Text
+    , vpnConnectionType :: Maybe Text
     , vpnConnectionCustomerGatewayId :: Text
     , vpnConnectionVpnGatewayId :: Text
     , vpnConnectionTagSet :: [ResourceTag]
@@ -1107,6 +1108,24 @@
     }
   deriving (Show, Read, Eq)
 
+data CreateRouteRequest
+    = CreateRouteToGateway
+        { createRouteTableId :: Text
+        , createRouteDestinationCidrBlock :: AddrRange IPv4
+        , createRouteGatewayId :: Text
+        }
+    | CreateRouteToInstance
+        { createRouteTableId :: Text
+        , createRouteDestinationCidrBlock :: AddrRange IPv4
+        , createRouteInstanceId :: Text
+        }
+    | CreateRouteToNetworkInterface
+        { createRouteTableId :: Text
+        , createRouteDestinationCidrBlock :: AddrRange IPv4
+        , createRouteNetworkInterfaceId :: Text
+        }
+  deriving (Show, Read, Eq)
+
 type PropagatingVgw = Text
 
 data Vpc = Vpc
@@ -1241,6 +1260,7 @@
 data NetworkInterfaceStatus
     = NetworkInterfaceStatusAvailable
     | NetworkInterfaceStatusInUse
+    | NetworkInterfaceStatusPending
   deriving (Show, Read, Eq)
 
 data NetworkInterfaceAttachment = NetworkInterfaceAttachment
@@ -1356,4 +1376,4 @@
     ["pending", "available", "deleting", "deleted"]
 deriveFromText "InternetGatewayAttachmentState"
     ["attaching", "attached", "detaching", "detached", "available"]
-deriveFromText "NetworkInterfaceStatus" ["available", "in-use"]
+deriveFromText "NetworkInterfaceStatus" ["available", "in-use", "pending"]
diff --git a/AWS/EC2/Util.hs b/AWS/EC2/Util.hs
--- a/AWS/EC2/Util.hs
+++ b/AWS/EC2/Util.hs
@@ -25,7 +25,6 @@
 import Control.Parallel (par)
 import Data.List (find)
 import qualified Control.Exception.Lifted as E
-import Control.Monad.Trans.Control (MonadBaseControl)
 
 import AWS.EC2.Internal
 import AWS.EC2.Types (ResourceTag(resourceTagKey))
diff --git a/AWS/EC2/VPC.hs b/AWS/EC2/VPC.hs
--- a/AWS/EC2/VPC.hs
+++ b/AWS/EC2/VPC.hs
@@ -4,11 +4,13 @@
     ( associateDhcpOptions
     , attachInternetGateway
     , createVpc
+    , createVpnConnection
     , createVpnGateway
     , createCustomerGateway
     , createInternetGateway
     , createDhcpOptions
     , deleteVpc
+    , deleteVpnConnection
     , deleteVpnGateway
     , deleteCustomerGateway
     , deleteInternetGateway
@@ -26,7 +28,6 @@
 import Data.XML.Types (Event)
 import Data.Conduit
 import Data.IP (IPv4, AddrRange)
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
@@ -35,8 +36,6 @@
 import AWS.Lib.Parser
 import AWS.Util
 
-import Debug.Trace
-
 ------------------------------------------------------------
 -- attachInternetGateway
 ------------------------------------------------------------
@@ -115,27 +114,29 @@
 internetGatewayAttachmentSink = InternetGatewayAttachment
     <$> getT "vpcId"
     <*> getT "state"
+
+------------------------------------------------------------
+-- describeVpnConnections
+------------------------------------------------------------
 describeVpnConnections
     :: (MonadBaseControl IO m, MonadResource m)
     => [Text] -- ^ VpnConnectionIds
-    -> [Filter]
+    -> [Filter] -- ^ Filters
     -> EC2 m (ResumableSource m VpnConnection)
 describeVpnConnections ids filters =
-    ec2QuerySource "DescribeVpnConnections" params vpnConnectionConduit
+    ec2QuerySource "DescribeVpnConnections" params $
+        itemConduit "vpnConnectionSet" vpnConnectionSink
   where
     params =
         [ "VpnConnectionId" |.#= ids
         , filtersParam filters
         ]
 
-vpnConnectionConduit
-    :: (MonadBaseControl IO m, MonadResource m)
-    => GLConduit Event m VpnConnection
-vpnConnectionConduit = itemConduit "vpnConnectionSet" $
-    VpnConnection
-    <$> do
-        a <- getT "vpnConnectionId"
-        traceShow a $ return a
+vpnConnectionSink
+    :: MonadThrow m
+    => GLSink Event m VpnConnection
+vpnConnectionSink = VpnConnection
+    <$> getT "vpnConnectionId"
     <*> getT "state"
     <*> getT "customerGatewayConfiguration"
     <*> getT "type"
@@ -160,6 +161,38 @@
         <*> getT "source"
         <*> getT "state"
         )
+
+------------------------------------------------------------
+-- createVpnConnection
+------------------------------------------------------------
+createVpnConnection
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ Type. The valid value is ipsec.1
+    -> Text -- ^ CustomerGatewayId
+    -> Text -- ^ VpnGatewayId
+    -> Maybe Text -- ^ AvailabilityZone
+    -> Maybe Bool -- ^ Option
+    -> EC2 m VpnConnection
+createVpnConnection type' cgid vgid zone option =
+    ec2Query "CreateVpnConnection" params $
+        element "vpnConnection" vpnConnectionSink
+  where
+    params =
+        [ "Type" |= type'
+        , "CustomerGatewayId" |= cgid
+        , "VpnGatewayId" |= vgid
+        , "AvailabilityZone" |=? zone
+        , "Options" |.+ "StaticRoutesOnly" |=? boolToText <$> option
+        ]
+
+------------------------------------------------------------
+-- deleteVpnConnection
+------------------------------------------------------------
+deleteVpnConnection
+    :: (MonadResource m, MonadBaseControl IO m)
+    => Text -- ^ VpnConnectionId
+    -> EC2 m Bool
+deleteVpnConnection = ec2Delete "DeleteVpnConnection" "VpnConnectionId"
 
 ------------------------------------------------------------
 -- describeVpcs
diff --git a/AWS/EC2/Volume.hs b/AWS/EC2/Volume.hs
--- a/AWS/EC2/Volume.hs
+++ b/AWS/EC2/Volume.hs
@@ -15,7 +15,6 @@
 
 import Data.XML.Types (Event)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Applicative
 
 import AWS.EC2.Internal
diff --git a/AWS/ELB.hs b/AWS/ELB.hs
--- a/AWS/ELB.hs
+++ b/AWS/ELB.hs
@@ -11,7 +11,6 @@
 
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Monad.IO.Class (MonadIO)
 import qualified Control.Monad.State as State
 import qualified Network.HTTP.Conduit as HTTP
diff --git a/AWS/ELB/Internal.hs b/AWS/ELB/Internal.hs
--- a/AWS/ELB/Internal.hs
+++ b/AWS/ELB/Internal.hs
@@ -5,7 +5,6 @@
 
 import Data.ByteString (ByteString)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.XML.Types (Event(..))
 
 import AWS.Class
diff --git a/AWS/ELB/LoadBalancer.hs b/AWS/ELB/LoadBalancer.hs
--- a/AWS/ELB/LoadBalancer.hs
+++ b/AWS/ELB/LoadBalancer.hs
@@ -7,7 +7,6 @@
 import Data.Text (Text)
 import Data.Conduit
 import Control.Applicative
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.XML.Types (Event(..))
 
 import AWS.Lib.Parser
diff --git a/AWS/Lib/Query.hs b/AWS/Lib/Query.hs
--- a/AWS/Lib/Query.hs
+++ b/AWS/Lib/Query.hs
@@ -3,6 +3,7 @@
 module AWS.Lib.Query
     ( QueryParam
     , Filter
+    , showUnitParams
     , (|.+)
     , putNumberV, putNumberP
     , filtersParam
@@ -30,7 +31,6 @@
 import Data.Monoid
 import Data.XML.Types (Event(..))
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import qualified Network.HTTP.Conduit as HTTP
 import qualified Text.XML.Stream.Parse as XmlP
 import Data.Time (UTCTime, formatTime, getCurrentTime)
@@ -59,6 +59,17 @@
 data QueryParam
     = Leaf Text Text
     | Inner Text [QueryParam]
+
+instance Show QueryParam where
+    show = show . paramToText
+
+paramToText :: QueryParam -> Text
+paramToText (Leaf k v) = k <> "=" <> v
+paramToText p@(Inner _ _) =
+    T.intercalate "&" . map paramToText $ partition p
+
+showUnitParams :: [QueryParam] -> [String]
+showUnitParams = map show . concat . map partition
 
 infixr 3 |.+
 (|.+) :: Text -> QueryParam -> QueryParam
diff --git a/AWS/RDS.hs b/AWS/RDS.hs
--- a/AWS/RDS.hs
+++ b/AWS/RDS.hs
@@ -7,11 +7,12 @@
     , setRegion
       -- * DBInstance
     , module AWS.RDS.DBInstance
+      -- * DBSnapshot
+    , module AWS.RDS.DBSnapshot
     ) where
 
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Control.Monad.IO.Class (MonadIO)
 import qualified Control.Monad.State as State
 import qualified Network.HTTP.Conduit as HTTP
@@ -23,6 +24,7 @@
 import AWS
 import AWS.RDS.Internal
 import AWS.RDS.DBInstance
+import AWS.RDS.DBSnapshot
 
 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
@@ -7,7 +7,6 @@
 import Data.Text (Text)
 import Data.Conduit
 import Control.Applicative
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.XML.Types (Event(..))
 import Data.Maybe (catMaybes)
 
diff --git a/AWS/RDS/DBSnapshot.hs b/AWS/RDS/DBSnapshot.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/DBSnapshot.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE FlexibleContexts, RankNTypes #-}
+
+module AWS.RDS.DBSnapshot
+    ( describeDBSnapshots
+    , createDBSnapshot
+    , deleteDBSnapshot
+    ) where
+
+import Data.Text (Text)
+import Data.Conduit
+import Control.Applicative
+import Data.XML.Types (Event(..))
+
+import AWS.Util
+import AWS.Lib.Query
+import AWS.Lib.Parser
+
+import AWS.RDS.Types
+import AWS.RDS.Internal
+
+describeDBSnapshots
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Maybe Text -- ^ DBInstanceIdentifier
+    -> Maybe Text -- ^ DBSnapshotIdentifier
+    -> Maybe Text -- ^ Marker
+    -> Maybe Int -- ^ MaxRecords
+    -> Maybe Text -- ^ SnapshotType
+    -> RDS m [DBSnapshot]
+describeDBSnapshots dbiid dbsid marker maxRecords sType =
+    rdsQuery "DescribeDBSnapshots" params sinkDBSnapshots
+  where
+    params =
+        [ "DBInstanceIdentifier" |=? dbiid
+        , "DBSnapshotIdentifier" |=? dbsid
+        , "Marker" |=? marker
+        , "MaxRecords" |=? toText <$> maxRecords
+        , "SnapshotType" |=? sType
+        ]
+
+sinkDBSnapshots
+    :: MonadThrow m
+    => GLSink Event m [DBSnapshot]
+sinkDBSnapshots = elements "DBSnapshot" sinkDBSnapshot
+
+sinkDBSnapshot
+    :: MonadThrow m
+    => GLSink Event m DBSnapshot
+sinkDBSnapshot = DBSnapshot
+    <$> getT "Port"
+    <*> getT "Iops"
+    <*> getT "Engine"
+    <*> getT "Status"
+    <*> getT "SnapshotType"
+    <*> getT "LicenseModel"
+    <*> getT "DBInstanceIdentifier"
+    <*> getT "EngineVersion"
+    <*> getT "DBSnapshotIdentifier"
+    <*> getT "SnapshotCreateTime"
+    <*> getT "VpcId"
+    <*> getT "AvailabilityZone"
+    <*> getT "InstanceCreateTime"
+    <*> getT "AllocatedStorage"
+    <*> getT "MasterUsername"
+
+createDBSnapshot
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ DBInstanceIdentifier
+    -> Text -- ^ DBSnapshotIdentifier
+    -> RDS m DBSnapshot
+createDBSnapshot dbiid dbsid =
+    rdsQuery "CreateDBSnapshot" params $
+        element "DBSnapshot" sinkDBSnapshot
+  where
+    params =
+        [ "DBInstanceIdentifier" |= dbiid
+        , "DBSnapshotIdentifier" |= dbsid
+        ]
+
+deleteDBSnapshot
+    :: (MonadBaseControl IO m, MonadResource m)
+    => Text -- ^ DBSnapshotIdentifier
+    -> RDS m DBSnapshot
+deleteDBSnapshot dbsid =
+    rdsQuery "DeleteDBSnapshot" params $
+        element "DBSnapshot" sinkDBSnapshot
+  where
+    params = ["DBSnapshotIdentifier" |= dbsid]
diff --git a/AWS/RDS/Internal.hs b/AWS/RDS/Internal.hs
--- a/AWS/RDS/Internal.hs
+++ b/AWS/RDS/Internal.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE FlexibleContexts, RankNTypes #-}
+{-# LANGUAGE FlexibleContexts, RankNTypes, CPP #-}
 
 module AWS.RDS.Internal
     where
@@ -6,7 +6,6 @@
 import Data.ByteString (ByteString)
 import Data.Text (Text)
 import Data.Conduit
-import Control.Monad.Trans.Control (MonadBaseControl)
 import Data.Monoid ((<>))
 import Data.XML.Types (Event(..))
 
@@ -14,6 +13,14 @@
 import AWS.Lib.Query
 import AWS.Lib.Parser
 
+#ifdef DEBUG
+import Control.Monad.IO.Class (liftIO)
+import qualified Control.Monad.Reader as Reader
+import qualified Control.Monad.State as State
+import Control.Monad.Trans.Class (lift)
+import qualified Data.Conduit.Binary as CB
+#endif
+
 apiVersion :: ByteString
 apiVersion = "2012-09-17"
 
@@ -32,3 +39,19 @@
     -> GLSink Event m a
     -> GLSink Event m [a]
 elements name f = element (name <> "s") $ listConsumer name f
+
+#ifdef DEBUG
+rdsQueryDebug
+    :: (MonadResource m, MonadBaseControl IO m)
+    => ByteString
+    -> [QueryParam]
+    -> RDS m a
+rdsQueryDebug action params = do
+    cred <- Reader.ask
+    ctx <- State.get
+    lift $ do
+        liftIO $ mapM_ putStrLn $ showUnitParams params
+        response <- requestQuery cred ctx action params apiVersion sinkError
+        (res, _) <- unwrapResumable response
+        res $$ CB.sinkFile "debug.txt" >>= fail "debug"
+#endif
diff --git a/AWS/RDS/Types.hs b/AWS/RDS/Types.hs
--- a/AWS/RDS/Types.hs
+++ b/AWS/RDS/Types.hs
@@ -91,3 +91,22 @@
     | PMVMultiAZ Bool
     | PMVPort Int
   deriving (Show, Eq)
+
+data DBSnapshot = DBSnapshot
+    { dbsPort :: Int
+    , dbsIops :: Maybe Int
+    , dbsEngine :: Text
+    , dbsStatus :: Text
+    , dbsSnapshotType :: Text
+    , dbsLicenseModel :: Text
+    , dbsDBInstanceIdentifier :: Text
+    , dbsEngineVersion :: Text
+    , dbsDBSnapshotIdentifier :: Text
+    , dbsSnapshotCreateTime :: Maybe UTCTime
+    , dbsVpcId :: Maybe Text
+    , dbsAvailabilityZone :: Text
+    , dbsInstanceCreateTime :: UTCTime
+    , dbsAllocatedStorage :: Int
+    , dbsMasterUsername :: Text
+    }
+  deriving (Show, Eq)
diff --git a/AWS/RDS/Util.hs b/AWS/RDS/Util.hs
new file mode 100644
--- /dev/null
+++ b/AWS/RDS/Util.hs
@@ -0,0 +1,28 @@
+module AWS.RDS.Util
+    ( wait
+    ) where
+
+import Control.Applicative ((<$>))
+import qualified Control.Concurrent as CC
+import Control.Monad.IO.Class (liftIO, MonadIO)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Safe
+
+import AWS.RDS
+
+wait
+    :: (MonadIO m, Functor m)
+    => (a -> Bool) -- ^ condition
+    -> (Text -> RDS m [a]) -- ^ DescribeResources
+    -> Text -- ^ Resource Id
+    -> RDS m a
+wait f g rid = do
+    mr <- headMay <$> g rid
+    case mr of
+        Nothing -> fail $ "Resource not found: " ++ T.unpack rid
+        Just r  -> if f r
+            then return r
+            else do
+                liftIO $ CC.threadDelay 10000000
+                wait f g rid
diff --git a/Tests/Main.hs b/Tests/Main.hs
--- a/Tests/Main.hs
+++ b/Tests/Main.hs
@@ -5,9 +5,11 @@
 module Main where
 
 import AWSTests.EC2Tests
+import AWSTests.RDSTests
 
 main :: IO ()
 main = do
+    -- EC2 Tests
     runInstanceTests
     runVpcTests
     runAddressTests
@@ -16,6 +18,7 @@
     runSubnetsTests
     runVolumeTests
     runSecurityGroupTests
+    runRouteTests
     runRouteTableTests
     runRegionTests
     runInstanceTests
@@ -23,3 +26,8 @@
     runTagTests
     runKeyPairTests
     runNetworkInterfaceTests
+    runNetworkInterfaceAttributeTests
+
+    -- RDS Tests
+    runDBInstanceTests
+    runDBSnapshotTests
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.8.0.0
+version:             0.9.0.0
 synopsis:            AWS SDK for Haskell
 description: AWS (Amazon Web Services) sdk for Haskell.
              .
@@ -26,6 +26,7 @@
                    , AWS.EC2.Metadata
                    , AWS.RDS
                    , AWS.RDS.Types
+                   , AWS.RDS.Util
                    , AWS.ELB
                    , AWS.ELB.Types
                    , AWS.CloudWatch
@@ -39,6 +40,7 @@
                    , AWS.EC2.Instance
                    , AWS.EC2.Volume
                    , AWS.EC2.KeyPair
+                   , AWS.EC2.Route
                    , AWS.EC2.RouteTable
                    , AWS.EC2.Snapshot
                    , AWS.EC2.SecurityGroup
@@ -48,6 +50,7 @@
                    , AWS.EC2.VPC
                    , AWS.EC2.Acl
                    , AWS.EC2.NetworkInterface
+                   , AWS.EC2.NetworkInterfaceAttribute
                    , AWS.EC2.Tag
                    , AWS.EC2.Params
                    , AWS.Lib.FromText
@@ -55,6 +58,7 @@
                    , AWS.Lib.Query
                    , AWS.RDS.Internal
                    , AWS.RDS.DBInstance
+                   , AWS.RDS.DBSnapshot
                    , AWS.ELB.Internal
                    , AWS.ELB.LoadBalancer
                    , AWS.CloudWatch.Internal
@@ -68,7 +72,7 @@
                    , base64-bytestring >= 1.0.0.0
                    , bytestring
                    , http-types
-                   , conduit >= 0.5.2
+                   , conduit >= 0.5.3
                    , transformers
                    , time
                    , old-locale
