diff --git a/amazonka.cabal b/amazonka.cabal
--- a/amazonka.cabal
+++ b/amazonka.cabal
@@ -1,5 +1,5 @@
 name:                  amazonka
-version:               0.0.8
+version:               0.1.0
 synopsis:              Comprehensive Amazon Web Services SDK
 homepage:              https://github.com/brendanhay/amazonka
 license:               OtherLicense
@@ -32,6 +32,7 @@
     exposed-modules:
           Control.Monad.Trans.AWS
         , Network.AWS
+        , Network.AWS.EC2.Metadata
 
     other-modules:
           Network.AWS.Internal.Auth
@@ -40,7 +41,7 @@
         , Network.AWS.Internal.Retry
 
     build-depends:
-          amazonka-core     == 0.0.8.*
+          amazonka-core     == 0.1.0.*
         , base              >= 4.7     && < 5
         , bytestring        >= 0.9
         , conduit           >= 1.1     && < 1.3
@@ -48,7 +49,7 @@
         , http-conduit      >= 2.1.4   && < 2.3
         , lens              >= 4.4     && < 5
         , mmorph            >= 1       && < 2
-        , monad-control     >= 0.3.2   && < 4
+        , monad-control     >= 0.3.2   && < 1
         , mtl               >= 2.2.1   && < 2.3
         , resourcet         >= 1.1     && < 1.3
         , retry             >= 0.5
diff --git a/src/Control/Monad/Trans/AWS.hs b/src/Control/Monad/Trans/AWS.hs
--- a/src/Control/Monad/Trans/AWS.hs
+++ b/src/Control/Monad/Trans/AWS.hs
@@ -34,6 +34,7 @@
     , paginateCatch
     -- ** Eventual consistency
     , await
+    , awaitCatch
     -- ** Pre-signing URLs
     , presign
     , presignURL
diff --git a/src/Network/AWS/EC2/Metadata.hs b/src/Network/AWS/EC2/Metadata.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/AWS/EC2/Metadata.hs
@@ -0,0 +1,327 @@
+{-# LANGUAGE BangPatterns      #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+-- Module      : Network.AWS.EC2.Metadata
+-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
+-- License     : This Source Code Form is subject to the terms of
+--               the Mozilla Public License, v. 2.0.
+--               A copy of the MPL can be found in the LICENSE file or
+--               you can obtain it at http://mozilla.org/MPL/2.0/.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+
+-- | Retrieve an EC2 instance's local metadata.
+module Network.AWS.EC2.Metadata
+    (
+    -- * Requests
+    -- ** Running on EC2
+      isEC2
+
+    -- ** Dynamic
+    , Dynamic   (..)
+    , dynamic
+
+    -- ** Metadata
+    , Metadata  (..)
+    , Mapping   (..)
+    , Info      (..)
+    , Interface (..)
+    , metadata
+
+    -- ** User data
+    , userdata
+    ) where
+
+import           Control.Applicative
+import           Control.Exception
+import           Control.Monad
+import           Control.Monad.Except
+import           Data.ByteString            (ByteString)
+import qualified Data.ByteString.Char8      as BS
+import qualified Data.ByteString.Lazy       as LBS
+import           Data.Maybe
+import           Data.Monoid
+import           Data.Text                  (Text)
+import qualified Data.Text                  as Text
+import           Network.AWS.Data
+import           Network.HTTP.Conduit
+
+data Dynamic
+    = FWS
+    -- ^ Value showing whether the customer has enabled detailed one-minute
+    -- monitoring in CloudWatch.
+    --
+    -- Valid values: enabled | disabled.
+    | Document
+    -- ^ JSON containing instance attributes, such as instance-id,
+    -- private IP address, etc.
+    | PKCS7
+    -- ^ Used to verify the document's authenticity and content against the
+    -- signature.
+    | Signature
+
+instance ToPath Dynamic where
+    toPath x = case x of
+       FWS       -> "fws/instance-monitoring"
+       Document  -> "instance-identity/document"
+       PKCS7     -> "instance-identity/pkcs7"
+       Signature -> "instance-identity/signature"
+
+data Metadata
+    = AMIId
+    -- ^ The AMI ID used to launch the instance.
+    | AMILaunchIndex
+    -- ^ If you started more than one instance at the same time, this value
+    -- indicates the order in which the instance was launched.
+    -- The value of the first instance launched is 0.
+    | AMIManifestPath
+    -- ^ The path to the AMI's manifest file in Amazon S3.
+    -- If you used an Amazon EBS-backed AMI to launch the instance,
+    -- the returned result is unknown.
+    | AncestorAMIIds
+    -- ^ The AMI IDs of any instances that were rebundled to create this AMI.
+    -- This value will only exist if the AMI manifest file contained an
+    -- ancestor-amis key.
+    | BlockDevice !Mapping
+    -- ^ See: 'Mapping'
+    | Hostname
+    -- ^ The private hostname of the instance. In cases where multiple network
+    -- interfaces are present, this refers to the eth0 device
+    -- (the device for which the device number is 0).
+    | IAM !Info
+    -- ^ See: 'Info'
+    | InstanceAction
+    -- ^ Notifies the instance that it should reboot in preparation for bundling.
+    -- Valid values: none | shutdown | bundle-pending.
+    | InstanceId
+    -- ^ The ID of this instance.
+    | InstanceType
+    -- ^ The type of instance.
+    --
+    -- See: @InstanceType@
+    | KernelId
+    -- ^ The ID of the kernel launched with this instance, if applicable.
+    | LocalHostname
+    -- ^ The private DNS hostname of the instance. In cases where multiple
+    -- network interfaces are present, this refers to the eth0 device
+    -- (the device for which the device number is 0).
+    | LocalIPV4
+    -- ^ The private IP address of the instance. In cases where multiple network
+    -- interfaces are present, this refers to the eth0 device
+    -- (the device for which the device number is 0).
+    | MAC
+    -- ^ The instance's media access control (MAC) address. In cases where
+    -- multiple network interfaces are present, this refers to the eth0 device
+    -- (the device for which the device number is 0).
+    | Network !Text !Interface
+    -- ^ See: 'Interface'
+    | AvailabilityZone
+    -- ^ The Availability Zone in which the instance launched.
+    | ProductCodes
+    -- ^ Product codes associated with the instance, if any.
+    | PublicHostname
+    -- ^ The instance's public DNS. If the instance is in a VPC, this category
+    -- is only returned if the enableDnsHostnames attribute is set to true.
+    -- For more information, see Using DNS with Your VPC.
+    | PublicIPV4
+    -- ^ The public IP address. If an Elastic IP address is associated with the
+    -- instance, the value returned is the Elastic IP address.
+    | OpenSSHKey
+    -- ^ Public key. Only available if supplied at instance launch time.
+    | RAMDiskId
+    -- ^ The ID of the RAM disk specified at launch time, if applicable.
+    | ReservationId
+    -- ^ ID of the reservation.
+    | SecurityGroups
+    -- ^ The names of the security groups applied to the instance.
+      deriving (Eq, Ord, Show)
+
+instance ToPath Metadata where
+    toPath x = case x of
+        AMIId            -> "ami-id"
+        AMILaunchIndex   -> "ami-launch-index"
+        AMIManifestPath  -> "ami-manifest-path"
+        AncestorAMIIds   -> "ancestor-ami-ids"
+        BlockDevice m    -> "block-device-mapping/" <> toPath m
+        Hostname         -> "hostname"
+        IAM m            -> "iam/" <> toPath m
+        InstanceAction   -> "instance-action"
+        InstanceId       -> "instance-id"
+        InstanceType     -> "instance-type"
+        KernelId         -> "kernel-id"
+        LocalHostname    -> "local-hostname"
+        LocalIPV4        -> "local-ipv4"
+        MAC              -> "mac"
+        Network n m      -> "network/interfaces/macs/" <> n <> "/" <> toPath m
+        AvailabilityZone -> "placement/availability-zone"
+        ProductCodes     -> "product-codes"
+        PublicHostname   -> "public-hostname"
+        PublicIPV4       -> "public-ipv4"
+        OpenSSHKey       -> "public-keys/0/openssh-key"
+        RAMDiskId        -> "ramdisk-id"
+        ReservationId    -> "reservation-id"
+        SecurityGroups   -> "security-groups"
+
+data Mapping
+    = AMI
+    -- ^ The virtual device that contains the root/boot file system.
+    | EBS !Int
+    -- ^ The virtual devices associated with Amazon EBS volumes, if present.
+    -- This value is only available in metadata if it is present at launch time.
+    -- The N indicates the index of the Amazon EBS volume (such as ebs1 or ebs2).
+    | Ephemeral !Int
+    -- ^ The virtual devices associated with ephemeral devices, if present.
+    -- The N indicates the index of the ephemeral volume.
+    | Root
+    -- ^ The virtual devices or partitions associated with the root devices,
+    -- or partitions on the virtual device, where the root (/ or C:) file system
+    -- is associated with the given instance.
+    | Swap
+    -- ^ The virtual devices associated with swap. Not always present.
+      deriving (Eq, Ord, Show)
+
+instance ToPath Mapping where
+    toPath x = case x of
+        AMI         -> "ami"
+        EBS       n -> "ebs"       <> toText n
+        Ephemeral n -> "ephemeral" <> toText n
+        Root        -> "root"
+        Swap        -> "root"
+
+data Interface
+    = IDeviceNumber
+    -- ^ The device number associated with that interface. Each interface must
+    -- have a unique device number. The device number serves as a hint to device
+    -- naming in the instance; for example, device-number is 2 for the eth2 device.
+    | IIPV4Associations !Text
+    -- ^ The private IPv4 addresses that are associated with each public-ip
+    -- address and assigned to that interface.
+    | ILocalHostname
+    -- ^ The interface's local hostname.
+    | ILocalIPV4s
+    -- ^ The private IP addresses associated with the interface.
+    | IMAC
+    -- ^ The instance's MAC address.
+    | IOwnerId
+    -- ^ The ID of the owner of the network interface. In multiple-interface
+    -- environments, an interface can be attached by a third party, such as
+    -- Elastic Load Balancing. Traffic on an interface is always billed to
+    -- the interface owner.
+    | IPublicHostname
+    -- ^ The interface's public DNS. If the instance is in a VPC, this category
+    -- is only returned if the enableDnsHostnames attribute is set to true.
+    -- For more information, see Using DNS with Your VPC.
+    | IPublicIPV4s
+    -- ^ The Elastic IP addresses associated with the interface. There may be
+    -- multiple IP addresses on an instance.
+    | ISecurityGroups
+    -- ^ Security groups to which the network interface belongs. Returned only
+    -- for instances launched into a VPC.
+    | ISecurityGroupIds
+    -- ^ IDs of the security groups to which the network interface belongs.
+    -- Returned only for instances launched into a VPC. For more information on
+    -- security groups in the EC2-VPC platform, see Security Groups for Your VPC.
+    | ISubnetId
+    -- ^ The ID of the subnet in which the interface resides. Returned only for
+    -- instances launched into a VPC.
+    | ISubnetIPV4_CIDRBlock
+    -- ^ The CIDR block of the subnet in which the interface resides. Returned
+    -- only for instances launched into a VPC.
+    | IVPCId
+    -- ^ The ID of the VPC in which the interface resides. Returned only for
+    -- instances launched into a VPC.
+    | IVPCIPV4_CIDRBlock
+    -- ^ The CIDR block of the VPC in which the interface resides. Returned only
+    -- for instances launched into a VPC.
+      deriving (Eq, Ord, Show)
+
+instance ToPath Interface where
+    toPath x = case x of
+        IDeviceNumber         -> "device-number"
+        IIPV4Associations ip  -> "ipv4-associations/" <> ip
+        ILocalHostname        -> "local-hostname"
+        ILocalIPV4s           -> "local-ipv4s"
+        IMAC                  -> "mac"
+        IOwnerId              -> "owner-id"
+        IPublicHostname       -> "public-hostname"
+        IPublicIPV4s          -> "public-ipv4s"
+        ISecurityGroups       -> "security-groups"
+        ISecurityGroupIds     -> "security-group-ids"
+        ISubnetId             -> "subnet-id"
+        ISubnetIPV4_CIDRBlock -> "subnet-ipv4-cidr-block"
+        IVPCId                -> "vpc-id"
+        IVPCIPV4_CIDRBlock    -> "vpc-ipv4-cidr-block"
+
+data Info
+    = Info
+    -- ^ Returns information about the last time the instance profile was updated,
+    -- including the instance's LastUpdated date, InstanceProfileArn,
+    -- and InstanceProfileId.
+    | SecurityCredentials (Maybe Text)
+    -- ^ Where role-name is the name of the IAM role associated with the instance.
+    -- Returns the temporary security credentials.
+    --
+    -- See: 'Auth' for JSON deserialisation.
+      deriving (Eq, Ord, Show)
+
+instance ToPath Info where
+    toPath x = case x of
+        Info                  -> "info"
+        SecurityCredentials r -> "security-credentials/" <> fromMaybe "" r
+
+-- | Test whether the host is running on EC2 by requesting the instance-data.
+isEC2 :: Manager -> IO Bool
+isEC2 m = liftIO (req `catch` err)
+  where
+    req = do
+        !_ <- request m "http://instance-data/latest"
+        return True
+
+    err :: IOException -> IO Bool
+    err = const (return False)
+
+dynamic :: MonadIO m
+        => Manager
+        -> Dynamic
+        -> ExceptT HttpException m ByteString
+dynamic m = get m . mappend "http://169.254.169.254/latest/dynamic/" . toPath
+
+metadata :: MonadIO m
+         => Manager
+         -> Metadata
+         -> ExceptT HttpException m ByteString
+metadata m = get m . mappend "http://169.254.169.254/latest/meta-data/" . toPath
+
+userdata :: MonadIO m
+         => Manager
+         -> ExceptT HttpException m (Maybe ByteString)
+userdata m = Just
+    `liftM` get m "http://169.254.169.254/latest/user-data"
+    `catchError` err
+  where
+    err (StatusCodeException s _ _) | fromEnum s == 404
+          = return Nothing
+    err e = throwError e
+
+get :: MonadIO m
+    => Manager
+    -> Text
+    -> ExceptT HttpException m ByteString
+get m url = ExceptT . liftIO $ req `catch` err
+  where
+    req = Right . strip <$> request m url
+
+    strip bs
+        | BS.isSuffixOf "\n" bs = BS.init bs
+        | otherwise             = bs
+
+    err :: HttpException -> IO (Either HttpException a)
+    err = return . Left
+
+request :: Manager -> Text -> IO ByteString
+request m url = do
+    rq <- parseUrl (Text.unpack url)
+    rs <- httpLbs (rq { responseTimeout = Just 2 }) m
+    return . LBS.toStrict $ responseBody rs
