diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,2 @@
-import Distribution.Simple
+import           Distribution.Simple
 main = defaultMain
diff --git a/exe/Main.hs b/exe/Main.hs
--- a/exe/Main.hs
+++ b/exe/Main.hs
@@ -1,6 +1,7 @@
 {-# language CPP                   #-}
 {-# language DataKinds             #-}
 {-# language FlexibleContexts      #-}
+{-# language LambdaCase            #-}
 {-# language OverloadedStrings     #-}
 {-# language PartialTypeSignatures #-}
 {-# language PolyKinds             #-}
@@ -14,6 +15,7 @@
 
 module Main where
 
+import qualified Data.Aeson                        as JSON
 import           Data.Conduit
 import           Data.Conduit.Combinators          (yieldMany)
 import           Data.List                         (find)
@@ -51,50 +53,78 @@
     (Proxy @'Nothing)
     (Proxy @('Just "Subscription"))
 
+data WritingMapping
+  = ABook (Integer, Integer) | AnArticle (Integer, Integer)
+
 type ServiceMapping = '[
-    "Book"   ':-> (Integer, Integer)
-  , "Author" ':-> Integer
+    "Book"    ':-> (Integer, Integer)
+  , "Article" ':-> (Integer, Integer)
+  , "Author"  ':-> Integer
+  , "Writing" ':-> WritingMapping
   ]
 
-library :: [(Integer, T.Text, [(Integer, T.Text)])]
+library :: [(Integer, T.Text, [(Integer, (T.Text, Integer))])]
 library
-  = [ (1, "Robert Louis Stevenson", [(1, "Treasure Island"), (2, "Strange Case of Dr Jekyll and Mr Hyde")])
-    , (2, "Immanuel Kant", [(3, "Critique of Pure Reason")])
-    , (3, "Michael Ende", [(4, "The Neverending Story"), (5, "Momo")])
+  = [ (1, "Robert Louis Stevenson", [(1, ("Treasure Island", 4)), (2, ("Strange Case of Dr Jekyll and Mr Hyde", 4))])
+    , (2, "Immanuel Kant", [(3, ("Critique of Pure Reason", 1))])
+    , (3, "Michael Ende", [(4, ("The Neverending Story", 5)), (5, ("Momo", 3))])
     ]
 
+articles :: [(Integer, T.Text, [(Integer, (T.Text, Integer))])]
+articles
+  = [ (1, "Fuencislo Robles", [(6, ("On Warm Chocolate", 4)), (2, ("On Cold Chocolate", 4))]) ]
+
 libraryServer :: forall m i. (MonadServer m)
               => ServerT ServiceMapping i ServiceDefinition m _
 libraryServer
-  = resolver ( object @"Book"   ( field  @"id"      bookId
+  = resolver ( object @"Book"   ( field  @"id"      bookOrArticleId
                                 , field  @"title"   bookTitle
-                                , field  @"author"  bookAuthor )
+                                , field  @"author"  bookOrArticleAuthor
+                                , field  @"info"    bookInfo )
+             , object @"Article" ( field @"id"      bookOrArticleId
+                                , field  @"title"   articleTitle
+                                , field  @"author"  bookOrArticleAuthor )
              , object @"Author" ( field  @"id"      authorId
                                 , field  @"name"    authorName
-                                , field  @"books"   authorBooks )
+                                , field  @"writings" authorBooks )
              , object @"Query"  ( method @"author"  findAuthor
                                 , method @"book"    findBookTitle
                                 , method @"authors" allAuthors
                                 , method @"books"   allBooks' )
              , object @"Subscription" ( method @"books" allBooksConduit )
+             , union @"Writing" (\case (ABook     x) -> pure $ unionChoice @"Book"    x
+                                       (AnArticle x) -> pure $ unionChoice @"Article" x)
              )
   where
     findBook i = find ((==i) . fst3) library
+    findArticle i = find ((==i) . fst3) articles
 
-    bookId (_, bid) = pure bid
-    bookTitle (aid, bid) = pure $ maybe "" (fromMaybe "" . lookup bid . thd3) (findBook aid)
-    bookAuthor (aid, _) = pure aid
+    bookOrArticleId (_, bid) = pure bid
+    bookOrArticleAuthor (aid, _) = pure aid
+    bookTitle (aid, bid) = pure $ fromMaybe "" $ do
+      bk <- findBook aid
+      ev <- lookup bid (thd3 bk)
+      pure (fst ev)
+    bookInfo (aid, bid) = pure $ do
+      bk <- findBook aid
+      ev <- lookup bid (thd3 bk)
+      pure $ JSON.object ["score" JSON..= snd ev]
+    articleTitle (aid, bid) = pure $ fromMaybe "" $ do
+      bk <- findArticle aid
+      ev <- lookup bid (thd3 bk)
+      pure (fst ev)
 
     authorId = pure
     authorName aid = pure $ maybe "" snd3 (findBook aid)
-    authorBooks aid = pure $ maybe [] (map ((aid,) . fst) . thd3) (findBook aid)
+    authorBooks aid = pure $ maybe [] (map (ABook . (aid,) . fst) . thd3) (findBook aid)
+                           <> maybe [] (map (AnArticle . (aid,) . fst) . thd3) (findArticle aid)
 
     findAuthor rx = pure $ listToMaybe
       [aid | (aid, name, _) <- library, name =~ rx]
 
     findBookTitle rx = pure $ listToMaybe
       [(aid, bid) | (aid, _, books) <- library
-                  , (bid, title) <- books
+                  , (bid, (title, _)) <- books
                   , title =~ rx]
 
     allAuthors = pure $ fst3 <$> library
diff --git a/exe/schema.graphql b/exe/schema.graphql
--- a/exe/schema.graphql
+++ b/exe/schema.graphql
@@ -2,12 +2,21 @@
   id: Int!
   title: String!
   author: Author!
+  info: JSON
 }
 
+type Article {
+  id: Int!
+  title: String!
+  author: Author!
+}
+
+union Writing = Book | Article
+
 type Author {
   id: Int!
   name: String!
-  books: [Book!]!
+  writings: [Writing!]!
 }
 
 type Query {
diff --git a/mu-graphql.cabal b/mu-graphql.cabal
--- a/mu-graphql.cabal
+++ b/mu-graphql.cabal
@@ -1,5 +1,5 @@
 name:          mu-graphql
-version:       0.4.1.0
+version:       0.5.0.0
 synopsis:      GraphQL support for Mu
 description:   GraphQL servers and clients for Mu-Haskell
 cabal-version: >=1.10
@@ -40,8 +40,8 @@
     , list-t                >=1.0   && <2
     , megaparsec            >=8     && <10
     , mtl                   >=2.2   && <2.3
-    , mu-rpc                ==0.4.*
-    , mu-schema             ==0.3.*
+    , mu-rpc                >=0.5   && <0.6
+    , mu-schema             >=0.3   && <0.4
     , parsers               >=0.12  && <0.13
     , scientific            >=0.3   && <0.4
     , sop-core              >=0.5   && <0.6
@@ -70,10 +70,11 @@
   ghc-options:      -Wall -threaded
   build-depends:
       base        >=4.12  && <5
+    , aeson       >=1.4   && <2
     , conduit     >=1.3.2 && <1.4
     , mu-graphql
-    , mu-rpc      ==0.4.*
-    , mu-schema   ==0.3.*
+    , mu-rpc      >=0.5   && <0.6
+    , mu-schema   >=0.3   && <0.4
     , regex-tdfa  >=1.3   && <2
     , text        >=1.2   && <2
     , wai-extra   >=3     && <4
diff --git a/src/Mu/GraphQL/Quasi.hs b/src/Mu/GraphQL/Quasi.hs
--- a/src/Mu/GraphQL/Quasi.hs
+++ b/src/Mu/GraphQL/Quasi.hs
@@ -15,6 +15,7 @@
 ) where
 
 import           Control.Monad.IO.Class      (liftIO)
+import qualified Data.Aeson                  as JSON
 import           Data.Foldable               (toList)
 import qualified Data.HashMap.Strict         as HM
 import           Data.List                   (foldl')
@@ -60,7 +61,8 @@
   | Object
   | Scalar
   | InputObject
-  | Other
+  | Union
+  | Interface
 
 classifySchema :: [GQL.TypeSystemDefinition] -> SchemaMap
 classifySchema = foldl' schemaToMap HM.empty
@@ -80,9 +82,9 @@
     typeToKeyValue (GQL.ObjectTypeDefinition _ name _ _ _)
       = (name, Object)
     typeToKeyValue (GQL.InterfaceTypeDefinition _ name _ _)
-      = (name, Other)
+      = (name, Interface)
     typeToKeyValue (GQL.UnionTypeDefinition _ name _ _)
-      = (name, Other)
+      = (name, Union)
     typeToKeyValue (GQL.EnumTypeDefinition _ name _ _)
       = (name, Enum)
     typeToKeyValue (GQL.InputObjectTypeDefinition _ name _ _)
@@ -117,8 +119,11 @@
 typeToDec :: Name -> TypeMap -> SchemaMap -> GQL.TypeDefinition -> Q Result
 typeToDec _ _ _ GQL.InterfaceTypeDefinition {}
   = fail "interface types are not supported"
-typeToDec _ _ _ GQL.UnionTypeDefinition {}
-  = fail "union types are not supported"
+typeToDec _ _ _ (GQL.UnionTypeDefinition _ nm _ (GQL.UnionMemberTypes elts)) = do
+  selts <- mapM textToStrLit elts
+  GQLService <$> [t| 'OneOf $(textToStrLit nm)
+                            $(pure $ typesToList selts) |]
+             <*> pure []
 typeToDec schemaName tm _ (GQL.ScalarTypeDefinition _ s _) =
   GQLScalar <$ gqlTypeToType s tm schemaName
 typeToDec schemaName tm sm (GQL.ObjectTypeDefinition _ nm _ _ flds) = do
@@ -189,25 +194,32 @@
     ginputTypeToType (GQL.TypeNonNull (GQL.NonNullTypeNamed a)) =
       [t| $(typeToPrimType a) |]
     ginputTypeToType (GQL.TypeNonNull (GQL.NonNullTypeList a)) =
-      [t| 'ListRef $(ginputTypeToType a) |]
+      [t| 'TList $(ginputTypeToType a) |]
     ginputTypeToType (GQL.TypeNamed a) =
-      [t| 'OptionalRef $(typeToPrimType a) |]
+      [t| 'TOption $(typeToPrimType a) |]
     ginputTypeToType (GQL.TypeList a) =
-      [t| 'OptionalRef ('ListRef $(ginputTypeToType a)) |]
+      [t| 'TOption ('TList $(ginputTypeToType a)) |]
     typeToPrimType :: GQL.Name -> Q Type
-    typeToPrimType "Int"     = [t|'TPrimitive Integer|]
-    typeToPrimType "Float"   = [t|'TPrimitive Double|]
-    typeToPrimType "String"  = [t|'TPrimitive T.Text|]
-    typeToPrimType "Boolean" = [t|'TPrimitive Bool|]
-    typeToPrimType "ID"      = [t|'TPrimitive UUID|]
-    typeToPrimType nm        = [t|'TSchematic $(textToStrLit nm)|]
+    typeToPrimType "Int"        = [t|'TPrimitive Integer|]
+    typeToPrimType "Float"      = [t|'TPrimitive Double|]
+    typeToPrimType "String"     = [t|'TPrimitive T.Text|]
+    typeToPrimType "Boolean"    = [t|'TPrimitive Bool|]
+    typeToPrimType "ID"         = [t|'TPrimitive UUID|]
+    typeToPrimType "JSON"       = [t|'TPrimitive JSON.Value|]
+    typeToPrimType "JSONObject" = [t|'TPrimitive JSON.Object|]
+    typeToPrimType nm           = [t|'TSchematic $(textToStrLit nm)|]
 
+-- For the JSON scalar we follow
+-- https://github.com/taion/graphql-type-json
+
 gqlTypeToType :: GQL.Name -> TypeMap -> Name -> Q Type
-gqlTypeToType "Int"     _ _ = [t|'PrimitiveRef Integer|]
-gqlTypeToType "Float"   _ _ = [t|'PrimitiveRef Double|]
-gqlTypeToType "String"  _ _ = [t|'PrimitiveRef T.Text|]
-gqlTypeToType "Boolean" _ _ = [t|'PrimitiveRef Bool|]
-gqlTypeToType "ID"      _ _ = [t|'PrimitiveRef UUID|]
+gqlTypeToType "Int"        _ _ = [t|'PrimitiveRef Integer|]
+gqlTypeToType "Float"      _ _ = [t|'PrimitiveRef Double|]
+gqlTypeToType "String"     _ _ = [t|'PrimitiveRef T.Text|]
+gqlTypeToType "Boolean"    _ _ = [t|'PrimitiveRef Bool|]
+gqlTypeToType "ID"         _ _ = [t|'PrimitiveRef UUID|]
+gqlTypeToType "JSON"       _ _ = [t|'PrimitiveRef JSON.Value|]
+gqlTypeToType "JSONObject" _ _ = [t|'PrimitiveRef JSON.Object|]
 gqlTypeToType name tm schemaName =
   let schemaRef = [t|'SchemaRef $(conT schemaName) $(textToStrLit name)|]
    in case HM.lookup name tm of
diff --git a/src/Mu/GraphQL/Query/Definition.hs b/src/Mu/GraphQL/Query/Definition.hs
--- a/src/Mu/GraphQL/Query/Definition.hs
+++ b/src/Mu/GraphQL/Query/Definition.hs
@@ -8,6 +8,7 @@
 import           Data.SOP.NP
 import           Data.SOP.NS
 import           Data.Text
+import           Data.Typeable
 import qualified Language.GraphQL.AST as GQL
 import           Mu.Rpc
 import           Mu.Schema
@@ -27,9 +28,12 @@
     => OneMethodQuery ('Package pname ss) (LookupService ss sub)
     -> Document ('Package pname ss) qr mut ('Just sub)
 
-type ServiceQuery (p :: Package snm mnm anm (TypeRef snm))
-                  (s :: Service snm mnm anm (TypeRef snm))
-  = [OneMethodQuery p s]
+data ServiceQuery (p :: Package snm mnm anm (TypeRef snm))
+                  (s :: Service snm mnm anm (TypeRef snm)) where
+  ServiceQuery :: [OneMethodQuery p ('Service nm ms)]
+               -> ServiceQuery p ('Service nm ms)
+  OneOfQuery   :: NP (ChosenOneOfQuery p) elts
+               -> ServiceQuery p ('OneOf nm elts)
 
 data OneMethodQuery (p :: Package snm mnm anm (TypeRef snm))
                     (s :: Service snm mnm anm (TypeRef snm)) where
@@ -40,17 +44,23 @@
   -- the special '__typename' field
   TypeNameQuery
     :: Maybe Text
-    -> OneMethodQuery p ('Service nm ms)
+    -> OneMethodQuery p s
   -- introspection fields
   SchemaQuery
     :: Maybe Text
     -> [GQL.Selection]
-    -> OneMethodQuery p ('Service nm ms)
+    -> OneMethodQuery p s
   TypeQuery
     :: Maybe Text
     -> Text
     -> [GQL.Selection]
-    -> OneMethodQuery p ('Service nm ms)
+    -> OneMethodQuery p s
+
+data ChosenOneOfQuery p elt where
+  ChosenOneOfQuery
+    :: Typeable elt => Proxy elt
+    -> ServiceQuery ('Package pname ss) (LookupService ss elt)
+    -> ChosenOneOfQuery ('Package pname ss) elt
 
 data ChosenMethodQuery (p :: Package snm mnm anm (TypeRef snm))
                        (m :: Method snm mnm anm (TypeRef snm)) where
diff --git a/src/Mu/GraphQL/Query/Introspection.hs b/src/Mu/GraphQL/Query/Introspection.hs
--- a/src/Mu/GraphQL/Query/Introspection.hs
+++ b/src/Mu/GraphQL/Query/Introspection.hs
@@ -11,6 +11,7 @@
 module Mu.GraphQL.Query.Introspection where
 
 import           Control.Monad.Writer
+import qualified Data.Aeson           as JSON
 import qualified Data.HashMap.Strict  as HM
 import qualified Data.HashSet         as S
 import           Data.Int             (Int32)
@@ -32,11 +33,12 @@
 
 data Type
   = Type
-    { kind       :: TypeKind
-    , typeName   :: Maybe T.Text
-    , fields     :: [Field]
-    , enumValues :: [EnumValue]
-    , ofType     :: Maybe Type
+    { kind          :: TypeKind
+    , typeName      :: Maybe T.Text
+    , fields        :: [Field]
+    , enumValues    :: [EnumValue]
+    , possibleTypes :: [Type]
+    , ofType        :: Maybe Type
     }
   | TypeRef { to :: T.Text }
   deriving Show
@@ -73,17 +75,17 @@
   deriving Show
 
 tSimple :: T.Text -> Type
-tSimple t = Type SCALAR (Just t) [] [] Nothing
+tSimple t = Type SCALAR (Just t) [] [] [] Nothing
 
 tList :: Type -> Type
-tList = Type LIST Nothing [] [] . Just
+tList = Type LIST Nothing [] [] [] . Just
 
 tNonNull :: Type -> Type
-tNonNull = Type NON_NULL Nothing [] [] . Just
+tNonNull = Type NON_NULL Nothing [] [] [] . Just
 
 unwrapNonNull :: Type -> Maybe Type
-unwrapNonNull (Type NON_NULL _ _ _ x) = x
-unwrapNonNull _                       = Nothing
+unwrapNonNull (Type NON_NULL _ _ _ _ x) = x
+unwrapNonNull _                         = Nothing
 
 -- BUILD INTROSPECTION DATA
 -- ========================
@@ -104,7 +106,10 @@
     = let (_, ts) = runWriter $
            introspectServices (Proxy @ss) (Proxy @sub) >>
            tell (HM.fromList (
-             (\i -> (i, tSimple i)) <$> ["Null", "Int", "Float", "String", "Boolean", "ID"]))
+             (\i -> (i, tSimple i))
+               <$> [ "Null", "Int", "Float"
+                   , "String", "Boolean", "ID"
+                   , "JSON", "JSONObject" ] ))
           -- return only reachable types
           qrS  = maybeSymbolVal (Proxy @qr)
           mutS = maybeSymbolVal (Proxy @mut)
@@ -171,12 +176,32 @@
   introspectServices _ psub = do
     let name = T.pack $ symbolVal (Proxy @sname)
     fs <- introspectFields (Proxy @smethods) (Proxy @(IsSub sname sub))
-    let t = Type OBJECT (Just name) fs [] Nothing
+    let t = Type OBJECT (Just name) fs [] [] Nothing
     -- add this one to the mix
     tell (HM.singleton name t)
     -- continue with the rest
     introspectServices (Proxy @ss) psub
 
+instance ( KnownSymbol sname, KnownSymbols elts
+         , IntrospectServices ss sub )
+         => IntrospectServices ('OneOf sname elts ': ss) sub where
+  introspectServices _ psub = do
+    let name = T.pack $ symbolVal (Proxy @sname)
+        tys  = map tSimple (symbolsVal (Proxy @elts))
+        t    = Type UNION (Just name) [] [] tys Nothing
+    -- add this one to the mix
+    tell (HM.singleton name t)
+    -- continue with the rest
+    introspectServices (Proxy @ss) psub
+
+class KnownSymbols (ss :: [Symbol]) where
+  symbolsVal :: Proxy ss -> [T.Text]
+instance KnownSymbols '[] where
+  symbolsVal _ = []
+instance (KnownSymbol s, KnownSymbols ss)
+         => KnownSymbols (s ': ss) where
+  symbolsVal _ = T.pack (symbolVal (Proxy @s)) : symbolsVal (Proxy @ss)
+
 class IntrospectFields (fs :: [Method']) (isSub :: Bool) where
   introspectFields
     :: Proxy fs -> Proxy isSub -> Writer TypeMap [Field]
@@ -252,6 +277,10 @@
   introspectTypeRef _ _ = pure $ tNonNull $ tSimple "String"
 instance IntrospectTypeRef ('PrimitiveRef T.Text) where
   introspectTypeRef _ _ = pure $ tNonNull $ tSimple "String"
+instance IntrospectTypeRef ('PrimitiveRef JSON.Value) where
+  introspectTypeRef _ _ = pure $ tNonNull $ tSimple "JSON"
+instance IntrospectTypeRef ('PrimitiveRef JSON.Object) where
+  introspectTypeRef _ _ = pure $ tNonNull $ tSimple "JSONObject"
 
 instance (IntrospectTypeRef r)
          => IntrospectTypeRef ('ListRef r) where
@@ -284,7 +313,7 @@
   introspectSchema k suffix _ = do
     let name = T.pack (symbolVal (Proxy @name)) <> suffix
         fs   = introspectSchemaFields suffix (Proxy @fields)
-        t    = Type k (Just name) fs [] Nothing
+        t    = Type k (Just name) fs [] [] Nothing
     -- add this one to the mix
     tell (HM.singleton name t)
     -- continue with the rest
@@ -294,7 +323,7 @@
   introspectSchema k suffix _ = do
     let name = T.pack (symbolVal (Proxy @name)) <> suffix
         cs   = introspectSchemaEnum (Proxy @choices)
-        t    = Type ENUM (Just name) [] cs Nothing
+        t    = Type ENUM (Just name) [] cs [] Nothing
     -- add this one to the mix
     tell (HM.singleton name t)
     -- continue with the rest
@@ -329,6 +358,10 @@
   introspectSchemaFieldType _ _ = tNonNull $ tSimple "String"
 instance IntrospectSchemaFieldType ('Mu.TPrimitive T.Text) where
   introspectSchemaFieldType _ _ = tNonNull $ tSimple "String"
+instance IntrospectSchemaFieldType ('Mu.TPrimitive JSON.Value) where
+  introspectSchemaFieldType _ _ = tNonNull $ tSimple "JSON"
+instance IntrospectSchemaFieldType ('Mu.TPrimitive JSON.Object) where
+  introspectSchemaFieldType _ _ = tNonNull $ tSimple "JSONObject"
 
 instance (IntrospectSchemaFieldType r)
          => IntrospectSchemaFieldType ('Mu.TList r) where
diff --git a/src/Mu/GraphQL/Query/Parse.hs b/src/Mu/GraphQL/Query/Parse.hs
--- a/src/Mu/GraphQL/Query/Parse.hs
+++ b/src/Mu/GraphQL/Query/Parse.hs
@@ -139,14 +139,15 @@
     KnownName sub, ParseMethod p ('Service sub smethods) smethods
   ) => ParseTypedDoc p ('Just qr) ('Just mut) ('Just sub) where
   parseTypedDocQuery vmap frmap sset
-    = QueryDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = QueryDoc <$> parseQuery (Proxy @p) (Proxy @qr) vmap frmap sset
   parseTypedDocMutation vmap frmap sset
-    = MutationDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = MutationDoc <$> parseQuery (Proxy @p) (Proxy @mut) vmap frmap sset
   parseTypedDocSubscription vmap frmap sset
-    = do q <- parseQuery Proxy Proxy vmap frmap sset
+    = do q <- parseQuery (Proxy @p) (Proxy @sub) vmap frmap sset
          case q of
-           [one] -> pure $ SubscriptionDoc one
-           _     -> throwError "subscriptions may only have one field"
+           ServiceQuery [one]
+             -> pure $ SubscriptionDoc one
+           _ -> throwError "subscriptions may only have one field"
 
 instance
   ( p ~ 'Package pname ss,
@@ -156,9 +157,9 @@
     KnownName mut, ParseMethod p ('Service mut mmethods) mmethods
   ) => ParseTypedDoc p ('Just qr) ('Just mut) 'Nothing where
   parseTypedDocQuery vmap frmap sset
-    = QueryDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = QueryDoc <$> parseQuery (Proxy @p) (Proxy @qr) vmap frmap sset
   parseTypedDocMutation vmap frmap sset
-    = MutationDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = MutationDoc <$> parseQuery (Proxy @p) (Proxy @mut) vmap frmap sset
   parseTypedDocSubscription _ _ _
     = throwError "no subscriptions are defined in the schema"
 
@@ -170,14 +171,15 @@
     KnownName sub, ParseMethod p ('Service sub smethods) smethods
   ) => ParseTypedDoc p ('Just qr) 'Nothing ('Just sub) where
   parseTypedDocQuery vmap frmap sset
-    = QueryDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = QueryDoc <$> parseQuery (Proxy @p) (Proxy @qr) vmap frmap sset
   parseTypedDocMutation _ _ _
     = throwError "no mutations are defined in the schema"
   parseTypedDocSubscription vmap frmap sset
-    = do q <- parseQuery Proxy Proxy vmap frmap sset
+    = do q <- parseQuery (Proxy @p) (Proxy @sub) vmap frmap sset
          case q of
-           [one] -> pure $ SubscriptionDoc one
-           _     -> throwError "subscriptions may only have one field"
+           ServiceQuery [one]
+             -> pure $ SubscriptionDoc one
+           _ -> throwError "subscriptions may only have one field"
 
 instance
   ( p ~ 'Package pname ss,
@@ -185,7 +187,7 @@
     KnownName qr, ParseMethod p ('Service qr qmethods) qmethods
   ) => ParseTypedDoc p ('Just qr) 'Nothing 'Nothing where
   parseTypedDocQuery vmap frmap sset
-    = QueryDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = QueryDoc <$> parseQuery (Proxy @p) (Proxy @qr) vmap frmap sset
   parseTypedDocMutation _ _ _
     = throwError "no mutations are defined in the schema"
   parseTypedDocSubscription _ _ _
@@ -201,12 +203,13 @@
   parseTypedDocQuery _ _ _
     = throwError "no queries are defined in the schema"
   parseTypedDocMutation vmap frmap sset
-    = MutationDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = MutationDoc <$> parseQuery (Proxy @p) (Proxy @mut) vmap frmap sset
   parseTypedDocSubscription vmap frmap sset
-    = do q <- parseQuery Proxy Proxy vmap frmap sset
+    = do q <- parseQuery (Proxy @p) (Proxy @sub) vmap frmap sset
          case q of
-           [one] -> pure $ SubscriptionDoc one
-           _     -> throwError "subscriptions may only have one field"
+           ServiceQuery [one]
+             -> pure $ SubscriptionDoc one
+           _ -> throwError "subscriptions may only have one field"
 
 instance
   ( p ~ 'Package pname ss,
@@ -216,7 +219,7 @@
   parseTypedDocQuery _ _ _
     = throwError "no queries are defined in the schema"
   parseTypedDocMutation vmap frmap sset
-    = MutationDoc <$> parseQuery Proxy Proxy vmap frmap sset
+    = MutationDoc <$> parseQuery (Proxy @p) (Proxy @mut) vmap frmap sset
   parseTypedDocSubscription _ _ _
     = throwError "no subscriptions are defined in the schema"
 
@@ -230,10 +233,11 @@
   parseTypedDocMutation _ _ _
     = throwError "no mutations are defined in the schema"
   parseTypedDocSubscription vmap frmap sset
-    = do q <- parseQuery Proxy Proxy vmap frmap sset
+    = do q <- parseQuery (Proxy @p) (Proxy @sub) vmap frmap sset
          case q of
-           [one] -> pure $ SubscriptionDoc one
-           _     -> throwError "subscriptions may only have one field"
+           ServiceQuery [one]
+             -> pure $ SubscriptionDoc one
+           _ -> throwError "subscriptions may only have one field"
 
 instance
   ParseTypedDoc p 'Nothing 'Nothing 'Nothing where
@@ -263,60 +267,92 @@
       [ GQL.ObjectField a (GQL.Node (constToValue v) m) l
       | GQL.ObjectField a (GQL.Node v m) l <- n ]
 
+class ParseQuery (p :: Package') (s :: Symbol) where
+  parseQuery
+    :: ( MonadError T.Text f, p ~ 'Package pname ss )
+    => Proxy p -> Proxy s
+    -> VariableMap -> FragmentMap -> [GQL.Selection]
+    -> f (ServiceQuery p (LookupService ss s))
 
-parseQuery ::
-  forall (p :: Package') (s :: Symbol) pname ss methods f.
-  ( MonadError T.Text f, p ~ 'Package pname ss,
-    LookupService ss s ~ 'Service s methods,
-    KnownName s, ParseMethod p ('Service s methods) methods
-  ) =>
-  Proxy p ->
-  Proxy s ->
-  VariableMap -> FragmentMap -> [GQL.Selection] ->
-  f (ServiceQuery p (LookupService ss s))
-parseQuery _ _ _ _ [] = pure []
-parseQuery pp ps vmap frmap (GQL.FieldSelection fld : ss)
-  = (++) <$> (maybeToList <$> fieldToMethod fld)
-         <*> parseQuery pp ps vmap frmap ss
-  where
-    fieldToMethod :: GQL.Field -> f (Maybe (OneMethodQuery p ('Service sname methods)))
-    fieldToMethod f@(GQL.Field alias name args dirs sels _)
-      | any (shouldSkip vmap) dirs
-      = pure Nothing
-      | name == "__typename"
-      = case (args, sels) of
-          ([], []) -> pure $ Just $ TypeNameQuery alias
-          _        -> throwError "__typename does not admit arguments nor selection of subfields"
-      | name == "__schema"
-      = case args of
-          [] -> Just . SchemaQuery alias <$> unFragment frmap (F.toList sels)
-          _  -> throwError "__schema does not admit selection of subfields"
-      | name == "__type"
-      = let getString (GQL.String s)   = Just s
-            getString (GQL.Variable v) = HM.lookup v vmap >>= getString
-            getString _                = Nothing
-        in case args of
-          [GQL.Argument _ (GQL.Node val _) _]
-            -> case getString val of
-                 Just s -> Just . TypeQuery alias s <$> unFragment frmap sels
-                 _      -> throwError "__type requires a string argument"
-          _ -> throwError "__type requires one single argument"
-      | otherwise
-      = Just . OneMethodQuery alias
-         <$> selectMethod (Proxy @('Service s methods))
-                          (T.pack $ nameVal (Proxy @s))
-                          vmap frmap f
-parseQuery pp ps vmap frmap (GQL.FragmentSpreadSelection (GQL.FragmentSpread nm dirs _) : ss)
-  | Just fr <- HM.lookup nm frmap
-  = if not (any (shouldSkip vmap) dirs) && not (any (shouldSkip vmap) $ fdDirectives fr)
-       then (++) <$> parseQuery pp ps vmap frmap (fdSelectionSet fr)
-                 <*> parseQuery pp ps vmap frmap ss
-       else parseQuery pp ps vmap frmap ss
-  | otherwise  -- the fragment definition was not found
-  = throwError $ "fragment '" <> nm <> "' was not found"
-parseQuery _ _ _ _ (_ : _)  -- Inline fragments are not yet supported
-  = throwError "inline fragments are not (yet) supported"
+instance ( p ~ 'Package pname ss
+         , KnownName s
+         , ParseQuery' p s (LookupService ss s) )
+         => ParseQuery p s where
+  parseQuery pp ps = parseQuery' pp ps (Proxy @(LookupService ss s))
 
+class ParseQuery' (p :: Package') (s :: Symbol) (svc :: Service') where
+  parseQuery'
+    :: ( MonadError T.Text f, p ~ 'Package pname ss
+       , LookupService ss s ~ svc, KnownName s )
+    => Proxy p -> Proxy s -> Proxy svc
+    -> VariableMap -> FragmentMap -> [GQL.Selection]
+    -> f (ServiceQuery p svc)
+
+instance (ParseQueryOneOf p elts)
+         => ParseQuery' p s ('OneOf s elts) where
+  parseQuery' pp _ps _ vmap frmap fs
+    = OneOfQuery <$> parseQueryOneOf pp (Proxy @elts) vmap frmap fs
+
+class ParseQueryOneOf (p :: Package') (s :: [Symbol]) where
+  parseQueryOneOf
+    :: ( MonadError T.Text f, p ~ 'Package pname ss )
+    => Proxy p -> Proxy s
+    -> VariableMap -> FragmentMap -> [GQL.Selection]
+    -> f (NP (ChosenOneOfQuery p) s)
+
+instance ParseQueryOneOf p '[] where
+  parseQueryOneOf _ _ _ _ _ = pure Nil
+instance ( ParseQuery p s, KnownSymbol s
+         , ParseQueryOneOf p ss)
+         => ParseQueryOneOf p (s ': ss) where
+  parseQueryOneOf pp _ps vmap frmap sel
+    = (:*) <$> (ChosenOneOfQuery (Proxy @s) <$> parseQuery pp (Proxy @s) vmap frmap sel)
+           <*> parseQueryOneOf pp (Proxy @ss) vmap frmap sel
+
+instance ( ParseMethod p ('Service s methods) methods )
+         => ParseQuery' p s ('Service s methods) where
+  parseQuery' _pp _ps _psvc vmap frmap fs = ServiceQuery <$> go fs
+    where
+      go [] = pure []
+      go (GQL.FieldSelection fld : ss)
+            = (++) <$> (maybeToList <$> fieldToMethod fld) <*> go ss
+      go (GQL.FragmentSpreadSelection (GQL.FragmentSpread nm dirs _) : ss)
+        | Just fr <- HM.lookup nm frmap
+        = if not (any (shouldSkip vmap) dirs) && not (any (shouldSkip vmap) $ fdDirectives fr)
+            then (++) <$> go (fdSelectionSet fr) <*> go ss
+            else go ss
+        | otherwise  -- the fragment definition was not found
+        = throwError $ "fragment '" <> nm <> "' was not found"
+      go (_ : _)  -- Inline fragments are not yet supported
+        = throwError "inline fragments are not (yet) supported"
+      -- fieldToMethod :: GQL.Field -> f (Maybe (OneMethodQuery p ('Service sname methods)))
+      fieldToMethod f@(GQL.Field alias name args dirs sels _)
+        | any (shouldSkip vmap) dirs
+        = pure Nothing
+        | name == "__typename"
+        = case (args, sels) of
+            ([], []) -> pure $ Just $ TypeNameQuery alias
+            _        -> throwError "__typename does not admit arguments nor selection of subfields"
+        | name == "__schema"
+        = case args of
+            [] -> Just . SchemaQuery alias <$> unFragment frmap (F.toList sels)
+            _  -> throwError "__schema does not admit selection of subfields"
+        | name == "__type"
+        = let getString (GQL.String s)   = Just s
+              getString (GQL.Variable v) = HM.lookup v vmap >>= getString
+              getString _                = Nothing
+          in case args of
+            [GQL.Argument _ (GQL.Node val _) _]
+              -> case getString val of
+                  Just s -> Just . TypeQuery alias s <$> unFragment frmap sels
+                  _      -> throwError "__type requires a string argument"
+            _ -> throwError "__type requires one single argument"
+        | otherwise
+        = Just . OneMethodQuery alias
+          <$> selectMethod (Proxy @('Service s methods))
+                            (T.pack $ nameVal (Proxy @s))
+                            vmap frmap f
+
 shouldSkip :: VariableMap -> GQL.Directive -> Bool
 shouldSkip vmap (GQL.Directive nm [GQL.Argument ifn (GQL.Node v _) _] _)
   | nm == "skip", ifn == "if"
@@ -362,7 +398,7 @@
   selectMethod _ tyName _ _ (fName -> wanted)
     = throwError $ "field '" <> wanted <> "' was not found on type '" <> tyName <> "'"
 instance
-  ( KnownSymbol mname, ParseMethod p s ms
+  ( KnownName mname, ParseMethod p s ms
   , ParseArgs p s ('Method mname args r) args
   , ParseDifferentReturn p r) =>
   ParseMethod p s ('Method mname args r ': ms)
@@ -713,10 +749,8 @@
          => ParseReturn p ('OptionalRef r) where
   parseReturn vmap frmap fname s
     = RetOptional <$> parseReturn vmap frmap fname s
-instance ( p ~ 'Package pname ss,
-           LookupService ss s ~ 'Service s methods,
-           KnownName s, ParseMethod p ('Service s methods) methods
-         ) => ParseReturn p ('ObjectRef s) where
+instance ( p ~ 'Package pname ss, ParseQuery p s )
+         => ParseReturn p ('ObjectRef s) where
   parseReturn vmap frmap _ s
     = RetObject <$> parseQuery (Proxy @p) (Proxy @s) vmap frmap s
 
@@ -732,7 +766,7 @@
     = pure QueryEnum
   parseSchema _ _ fname _
     = throwError $ "field '" <> fname <> "' should not have a selection of subfields"
-instance (KnownSymbol name, ParseField sch fields)
+instance (KnownName name, ParseField sch fields)
          => ParseSchema sch ('DRecord name fields) where
   parseSchema vmap frmap _ s
     = QueryRecord <$> parseSchemaQuery (Proxy @sch) (Proxy @('DRecord name fields)) vmap frmap s
@@ -741,7 +775,7 @@
   forall (sch :: Schema') t (rname :: Symbol) fields f.
   ( MonadError T.Text f
   , t ~  'DRecord rname fields
-  , KnownSymbol rname
+  , KnownName rname
   , ParseField sch fields ) =>
   Proxy sch ->
   Proxy t ->
@@ -790,7 +824,7 @@
   selectField tyName _ _ wanted _
     = throwError $ "field '" <> wanted <> "' was not found on type '" <> tyName <> "'"
 instance
-  (KnownSymbol fname, ParseField sch fs, ParseSchemaReturn sch r) =>
+  (KnownName fname, ParseField sch fs, ParseSchemaReturn sch r) =>
   ParseField sch ('FieldDef fname r ': fs)
   where
   selectField tyName vmap frmap wanted sels
diff --git a/src/Mu/GraphQL/Query/Run.hs b/src/Mu/GraphQL/Query/Run.hs
--- a/src/Mu/GraphQL/Query/Run.hs
+++ b/src/Mu/GraphQL/Query/Run.hs
@@ -11,6 +11,7 @@
 {-# language ScopedTypeVariables   #-}
 {-# language TupleSections         #-}
 {-# language TypeApplications      #-}
+{-# language TypeFamilies          #-}
 {-# language TypeOperators         #-}
 {-# language UndecidableInstances  #-}
 {-# OPTIONS_GHC -fprint-explicit-foralls #-}
@@ -36,9 +37,11 @@
 import qualified Data.HashMap.Strict            as HM
 import           Data.Maybe
 import qualified Data.Text                      as T
+import           Data.Typeable
 import           GHC.TypeLits
 import qualified Language.GraphQL.AST           as GQL
 import           Network.HTTP.Types.Header
+import           Unsafe.Coerce                  (unsafeCoerce)
 
 import           Mu.GraphQL.Query.Definition
 import qualified Mu.GraphQL.Query.Introspection as Intro
@@ -233,11 +236,10 @@
   runConduit $ yieldMany ([val] :: [Aeson.Value]) .| sink
 
 runQuery
-  :: forall m p s pname ss hs sname ms chn inh.
+  :: forall m p s pname ss hs chn inh.
      ( RunQueryFindHandler m p hs chn ss s hs
      , p ~ 'Package pname ss
-     , s ~ 'Service sname ms
-     , inh ~ MappingRight chn sname )
+     , inh ~ MappingRight chn (ServiceName s) )
   => (forall a. m a -> ServerErrorIO a)
   -> RequestHeaders
   -> Intro.Schema -> ServerT chn GQL.Field p m hs
@@ -248,11 +250,10 @@
 runQuery f req sch whole@(Services ss) path = runQueryFindHandler f req sch whole path ss
 
 runSubscription
-  :: forall m p s pname ss hs sname ms chn inh.
+  :: forall m p s pname ss hs chn inh.
      ( RunQueryFindHandler m p hs chn ss s hs
      , p ~ 'Package pname ss
-     , s ~ 'Service sname ms
-     , inh ~ MappingRight chn sname )
+     , inh ~ MappingRight chn (ServiceName s) )
   => (forall a. m a -> ServerErrorIO a)
   -> RequestHeaders
   -> ServerT chn GQL.Field p m hs
@@ -267,8 +268,7 @@
 class RunQueryFindHandler m p whole chn ss s hs where
   runQueryFindHandler
     :: ( p ~ 'Package pname wholess
-       , s ~ 'Service sname ms
-       , inh ~ MappingRight chn sname )
+       , inh ~ MappingRight chn (ServiceName s) )
     => (forall a. m a -> ServerErrorIO a)
     -> RequestHeaders
     -> Intro.Schema -> ServerT chn GQL.Field p m whole
@@ -279,8 +279,7 @@
     -> WriterT [GraphQLError] IO Aeson.Value
   runSubscriptionFindHandler
     :: ( p ~ 'Package pname wholess
-       , s ~ 'Service sname ms
-       , inh ~ MappingRight chn sname )
+       , inh ~ MappingRight chn (ServiceName s) )
     => (forall a. m a -> ServerErrorIO a)
     -> RequestHeaders
     -> ServerT chn GQL.Field p m whole
@@ -291,6 +290,32 @@
     -> ConduitT Aeson.Value Void IO ()
     -> IO ()
 
+class RunQueryOnFoundHandler m p whole chn (s :: Service snm mnm anm (TypeRef snm)) hs where
+  type ServiceName s :: snm
+  runQueryOnFoundHandler
+    :: ( p ~ 'Package pname wholess
+       , inh ~ MappingRight chn (ServiceName s) )
+    => (forall a. m a -> ServerErrorIO a)
+    -> RequestHeaders
+    -> Intro.Schema -> ServerT chn GQL.Field p m whole
+    -> [T.Text]
+    -> ServiceT chn GQL.Field s m hs
+    -> inh
+    -> ServiceQuery p s
+    -> WriterT [GraphQLError] IO Aeson.Value
+  runSubscriptionOnFoundHandler
+    :: ( p ~ 'Package pname wholess
+       , inh ~ MappingRight chn (ServiceName s) )
+    => (forall a. m a -> ServerErrorIO a)
+    -> RequestHeaders
+    -> ServerT chn GQL.Field p m whole
+    -> [T.Text]
+    -> ServiceT chn GQL.Field s m hs
+    -> inh
+    -> OneMethodQuery p s
+    -> ConduitT Aeson.Value Void IO ()
+    -> IO ()
+
 instance TypeError ('Text "Could not find handler for " ':<>: 'ShowType s)
          => RunQueryFindHandler m p whole chn '[] s '[] where
   runQueryFindHandler _ = error "this should never be called"
@@ -302,17 +327,24 @@
     = runQueryFindHandler f req sch whole path that
   runSubscriptionFindHandler f req whole path (_ :<&>: that)
     = runSubscriptionFindHandler f req whole path that
-instance {-# OVERLAPS #-}
-         ( s ~ 'Service sname ms, KnownName sname
-         , RunMethod m p whole chn s ms h )
+instance {-# OVERLAPS #-}
+         (RunQueryOnFoundHandler m p whole chn s h)
          => RunQueryFindHandler m p whole chn (s ': ss) s (h ': hs) where
-  runQueryFindHandler f req sch whole path (this :<&>: _) inh queries
+  runQueryFindHandler f req sch whole path (s :<&>: _)
+    = runQueryOnFoundHandler f req sch whole path s
+  runSubscriptionFindHandler f req whole path (s :<&>: _)
+    = runSubscriptionOnFoundHandler f req whole path s
+
+instance ( KnownName sname, RunMethod m p whole chn ('Service sname ms) ms h )
+         => RunQueryOnFoundHandler m p whole chn ('Service sname ms) h where
+  type ServiceName ('Service sname ms) = sname
+  runQueryOnFoundHandler f req sch whole path (ProperSvc this) inh (ServiceQuery queries)
     = Aeson.object . catMaybes <$> mapM runOneQuery queries
     where
       -- if we include the signature we have to write
       -- an explicit type signature for 'runQueryFindHandler'
       runOneQuery (OneMethodQuery nm args)
-        = runMethod f req whole (Proxy @s) path nm inh this args
+        = runMethod f req whole (Proxy @('Service sname ms)) path nm inh this args
       -- handle __typename
       runOneQuery (TypeNameQuery nm)
         = let realName = fromMaybe "__typename" nm
@@ -333,23 +365,59 @@
                                     path]
                               pure $ Just (realName, Aeson.Null)
   -- subscriptions should only have one element
-  runSubscriptionFindHandler f req whole path (this :<&>: _) inh (OneMethodQuery nm args) sink
-    = runMethodSubscription f req whole (Proxy @s) path nm inh this args sink
-  runSubscriptionFindHandler _ _ _ _ _ _ (TypeNameQuery nm) sink
+  runSubscriptionOnFoundHandler f req whole path (ProperSvc this) inh (OneMethodQuery nm args) sink
+    = runMethodSubscription f req whole (Proxy @('Service sname ms)) path nm inh this args sink
+  runSubscriptionOnFoundHandler _ _ _ _ _ _ (TypeNameQuery nm) sink
     = let realName = fromMaybe "__typename" nm
           o = Aeson.object [(realName, Aeson.String $ T.pack $ nameVal (Proxy @sname))]
       in runConduit $ yieldMany ([o] :: [Aeson.Value]) .| sink
-  runSubscriptionFindHandler _ _ _ _ _ _ _ sink
+  runSubscriptionOnFoundHandler _ _ _ _ _ _ _ sink
     = runConduit $ yieldMany
                    ([singleErrValue "__schema and __type are not supported in subscriptions"]
                       :: [Aeson.Value])
                    .| sink
 
+instance ( KnownName sname, RunUnion m p whole chn elts )
+         => RunQueryOnFoundHandler m p whole chn ('OneOf sname elts) h where
+  type ServiceName ('OneOf sname elts) = sname
+  runQueryOnFoundHandler f req sch whole path (OneOfSvc this) inh (OneOfQuery queries)
+    = do res <- liftIO $ runExceptT $ f $ this inh
+         case res of
+          Left e  -> tell [GraphQLError e path] >> pure Aeson.Null
+          Right x -> runUnion f req sch whole path queries x
+  runSubscriptionOnFoundHandler _ _ _ _ (OneOfSvc _) _ _ _
+    = error "this should never happen"
+
+class RunUnion m p whole chn elts where
+  runUnion
+    :: (forall a. m a -> ServerErrorIO a)
+    -> RequestHeaders
+    -> Intro.Schema -> ServerT chn GQL.Field p m whole
+    -> [T.Text]
+    -> NP (ChosenOneOfQuery p) elts
+    -> UnionChoice chn elts
+    -> WriterT [GraphQLError] IO Aeson.Value
+
+instance RunUnion m p whole chn '[] where
+  runUnion _ = error "this should never happen"
+instance forall m p pname s sname whole ss chn elts.
+         ( RunQueryFindHandler m p whole chn ss s whole
+         , p ~ 'Package pname ss
+         , s ~ LookupService ss sname
+         , ServiceName s ~ sname
+         , RunUnion m p whole chn elts )
+         => RunUnion m p whole chn (sname ': elts) where
+  runUnion f req sch whole path
+           (ChosenOneOfQuery (Proxy :: Proxy sname) q :* rest)
+           choice@(UnionChoice (Proxy :: Proxy other) v)
+    = case eqT @sname @other of
+        Nothing   -> runUnion f req sch whole path rest (unsafeCoerce choice)
+        Just Refl -> runQuery @m @('Package pname ss) @(LookupService ss sname) @pname @ss @whole f req sch whole path v q
+
 class RunMethod m p whole chn s ms hs where
   runMethod
     :: ( p ~ 'Package pname wholess
-       , s ~ 'Service sname allMs
-       , inh ~ MappingRight chn sname )
+       , inh ~ MappingRight chn (ServiceName s) )
     => (forall a. m a -> ServerErrorIO a)
     -> RequestHeaders
     -> ServerT chn GQL.Field p m whole
@@ -359,8 +427,7 @@
     -> WriterT [GraphQLError] IO (Maybe (T.Text, Aeson.Value))
   runMethodSubscription
     :: ( p ~ 'Package pname wholess
-       , s ~ 'Service sname allMs
-       , inh ~ MappingRight chn sname )
+       , inh ~ MappingRight chn (ServiceName s) )
     => (forall a. m a -> ServerErrorIO a)
     -> RequestHeaders
     -> ServerT chn GQL.Field p m whole
@@ -385,6 +452,7 @@
           rpcInfo = reflectRpcInfo (Proxy @p) (Proxy @s) (Proxy @('Method mname args r)) req fld
   runMethod f req whole p path nm inh (_ :<||>: r) (S cont)
     = runMethod f req whole p path nm inh r cont
+  runMethod _ _ _ _ _ _ _ _ _ = error "this should never happen"
   -- handle subscriptions
   runMethodSubscription f req whole _ path nm inh (h :<||>: _) (Z (ChosenMethodQuery fld args ret)) sink
     = runHandlerSubscription f req whole (path ++ [realName]) (h rpcInfo inh) args ret sink
@@ -392,6 +460,7 @@
           rpcInfo = reflectRpcInfo (Proxy @p) (Proxy @s) (Proxy @('Method mname args r)) req fld
   runMethodSubscription f req whole p path nm inh (_ :<||>: r) (S cont) sink
     = runMethodSubscription f req whole p path nm inh r cont sink
+  runMethodSubscription _ _ _ _ _ _ _ _ _ _ = error "this should never happen"
 
 class Handles chn args r m h
       => RunHandler m p whole chn args r h where
@@ -518,9 +587,9 @@
   convertResult _ _ _ _ (RetSchema r) t
     = pure $ Just $ runSchemaQuery (toSchema' @_ @_ @sch @r t) r
 instance ( MappingRight chn ref ~ t
-         , MappingRight chn sname ~ t
-         , LookupService ss ref ~ 'Service sname ms
-         , RunQueryFindHandler m ('Package pname ss) whole chn ss ('Service sname ms) whole)
+         , MappingRight chn (ServiceName svc) ~ t
+         , LookupService ss ref ~ svc
+         , RunQueryFindHandler m ('Package pname ss) whole chn ss svc whole)
          => ResultConversion m ('Package pname ss) whole chn ('ObjectRef ref) t where
   convertResult f req whole path (RetObject q) h
     = Just <$> runQuery @m @('Package pname ss) @(LookupService ss ref) f req
@@ -643,7 +712,7 @@
   = case HM.lookup t ts of
       Nothing -> pure Nothing
       Just ty -> runIntroType path s ty ss
-runIntroType path s (Intro.Type k tnm fs vals ofT) ss
+runIntroType path s (Intro.Type k tnm fs vals posTys ofT) ss
   = do things <- catMaybes <$> traverse runOne ss
        pure $ Just $ Aeson.object things
   where
@@ -683,7 +752,12 @@
              ("interfaces", _)
                -> pure $ Just $ Aeson.Array []
              ("possibleTypes", _)
-               -> pure $ Just $ Aeson.Array []
+               -> case k of
+                    Intro.UNION
+                      -> do res <- catMaybes <$>
+                                     mapM (\o -> runIntroType path' s o innerss) posTys
+                            pure $ Just $ Aeson.toJSON res
+                    _ -> pure $ Just Aeson.Null
 
              _ -> do tell [GraphQLError
                              (ServerError Invalid
