diff --git a/Main.hs b/Main.hs
--- a/Main.hs
+++ b/Main.hs
@@ -94,9 +94,7 @@
         , (Simple,  ProtocolWriter " ::bond::SimpleBinaryWriter<::bond::OutputBuffer>")
         ]
     templates = concat $ map snd $ filter fst codegen_templates
-    codegen_templates = [ (core_enabled, core_files)
-                        , (grpc_enabled, [grpc_h export_attribute, grpc_cpp])
-                        ]
+    codegen_templates = [ (core_enabled, core_files) ]
     core_files = [
           reflection_h export_attribute
         , types_h export_attribute header enum_header allocator alloc_ctors_enabled type_aliases_enabled scoped_alloc_enabled
@@ -123,9 +121,7 @@
             then ConstructorParameters
             else DefaultWithProtectedBase
     templates = concat $ map snd $ filter fst codegen_templates
-    codegen_templates = [ (structs_enabled, [types_cs Class fieldMapping constructorOptions])
-                        , (grpc_enabled, [grpc_cs])
-                        ]
+    codegen_templates = [ (structs_enabled, [types_cs Class fieldMapping constructorOptions]) ]
 csCodegen _ = error "csCodegen: impossible happened."
 
 anyServiceInheritance :: [Declaration] -> Bool
@@ -142,9 +138,8 @@
     namespaceMapping <- parseNamespaceMappings $ namespace options
     (Bond imports namespaces declarations) <- parseFile (import_dir options) file
     let mappingContext = MappingContext typeMapping aliasMapping namespaceMapping namespaces
-    case (anyServiceInheritance declarations, service_inheritance_enabled options, grpc_enabled options) of
-        (True, False, _)   -> fail "Use --enable-service-inheritance to enable service inheritance syntax."
-        (True, True, True) -> fail "Service inheritance is not supported in gRPC codegen."
+    case (anyServiceInheritance declarations, service_inheritance_enabled options) of
+        (True, False)   -> fail "Use --enable-service-inheritance to enable service inheritance syntax."
         _                     -> forM_ templates $ \template -> do
                                     let (suffix, code) = template mappingContext baseName imports declarations
                                     let fileName = baseName ++ suffix
diff --git a/Options.hs b/Options.hs
--- a/Options.hs
+++ b/Options.hs
@@ -40,7 +40,6 @@
         , jobs :: Maybe Int
         , no_banner :: Bool
         , core_enabled :: Bool
-        , grpc_enabled :: Bool
         , alloc_ctors_enabled :: Bool
         , type_aliases_enabled :: Bool
         , scoped_alloc_enabled :: Bool
@@ -58,7 +57,6 @@
         , jobs :: Maybe Int
         , no_banner :: Bool
         , structs_enabled :: Bool
-        , grpc_enabled :: Bool
         , service_inheritance_enabled :: Bool
         , constructor_parameters :: Bool
         }
@@ -96,7 +94,6 @@
     , jobs = def &= opt "0" &= typ "NUM" &= name "j" &= help "Run NUM jobs simultaneously (or '$ncpus' if no NUM is not given)"
     , no_banner = def &= help "Omit the banner at the top of generated files"
     , core_enabled = True &= explicit &= name "core" &= help "Generate core serialization definitions (true by default, --core=false to disable)"
-    , grpc_enabled = False &= explicit &= name "grpc" &= help "Generate gRPC definitions"
     , alloc_ctors_enabled = False &= explicit &= name "alloc-ctors" &= help "Generate constructors with allocator argument"
     , type_aliases_enabled = False &= explicit &= name "type-aliases" &= help "Generate type aliases"
     , scoped_alloc_enabled = False &= explicit &= name "scoped-alloc" &= help "Use std::scoped_allocator_adaptor for strings and containers"
@@ -111,7 +108,6 @@
     , readonly_properties = def &= name "r" &= help "Generate private property setters"
     , fields = def &= name "f" &= help "Generate public fields rather than properties"
     , structs_enabled = True &= explicit &= name "structs" &= help "Generate C# types for Bond structs and enums (true by default, use \"--structs=false\" to disable)"
-    , grpc_enabled = False &= explicit &= name "grpc" &= help "Generate C# services and proxies for gRPC"
     , constructor_parameters = def &= explicit &= name "preview-constructor-parameters" &= help "PREVIEW FEATURE: Generate a constructor that takes all the fields as parameters. Typically used with readonly-properties."
     } &=
     name "c#" &=
diff --git a/bond.cabal b/bond.cabal
--- a/bond.cabal
+++ b/bond.cabal
@@ -1,13 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
+-- This file has been generated from package.yaml by hpack version 0.35.0.
 --
 -- see: https://github.com/sol/hpack
---
--- hash: 5f829cf187d9630385924b752fae193c51da82b2d9bfc0ef8f38f23a638fc604
 
 name:           bond
-version:        0.12.1.0
+version:        0.13.0.0
 synopsis:       Bond schema compiler and code generator
 description:    Bond is a cross-platform framework for handling schematized data. It supports cross-language de/serialization and powerful generic mechanisms for efficiently manipulating data. . This package contains a library for parsing the Bond schema definition language and performing template-based code generation. The library includes built-in templates for generating standard Bond C++ and C# code, as well as utilities for writing custom codegen templates. . The package also contains a command-line compiler/codegen tool, named gbc, which is primarily used to generate code for C++ and C# programs using Bond.
 category:       Language, Compiler, Code Generation
@@ -35,13 +33,10 @@
       Language.Bond.Codegen.Cpp.Apply_h
       Language.Bond.Codegen.Cpp.ApplyOverloads
       Language.Bond.Codegen.Cpp.Enum_h
-      Language.Bond.Codegen.Cpp.Grpc_cpp
-      Language.Bond.Codegen.Cpp.Grpc_h
       Language.Bond.Codegen.Cpp.Reflection_h
       Language.Bond.Codegen.Cpp.Types_cpp
       Language.Bond.Codegen.Cpp.Types_h
       Language.Bond.Codegen.Cpp.Util
-      Language.Bond.Codegen.Cs.Grpc_cs
       Language.Bond.Codegen.Cs.Types_cs
       Language.Bond.Codegen.Cs.Util
       Language.Bond.Codegen.CustomMapping
@@ -74,13 +69,13 @@
     , shakespeare
     , text
     , unordered-containers
+  default-language: Haskell2010
   if os(windows) && arch(i386)
     ld-options: -Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware
   if os(windows) && arch(x86_64)
     ld-options: -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va
   if flag(warningsAsErrors)
     ghc-options: -Wall -Werror
-  default-language: Haskell2010
 
 executable gbc
   main-is: Main.hs
@@ -89,7 +84,7 @@
       Options
       Paths_bond
   hs-source-dirs:
-      ./.
+      ./
   build-depends:
       aeson
     , async
@@ -107,6 +102,7 @@
     , shakespeare
     , text
     , unordered-containers
+  default-language: Haskell2010
   if os(windows) && arch(i386)
     ld-options: -Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware
   if os(windows) && arch(x86_64)
@@ -115,7 +111,6 @@
     ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Werror
   else
     ghc-options: -threaded -rtsopts -with-rtsopts=-N
-  default-language: Haskell2010
 
 test-suite gbc-tests
   type: exitcode-stdio-1.0
@@ -130,7 +125,7 @@
       Options
   hs-source-dirs:
       tests
-      ./.
+      ./
   build-depends:
       Diff
     , HUnit
@@ -156,6 +151,7 @@
     , tasty-quickcheck
     , text
     , unordered-containers
+  default-language: Haskell2010
   if os(windows) && arch(i386)
     ld-options: -Wl,--dynamicbase -Wl,--nxcompat -Wl,--large-address-aware
   if os(windows) && arch(x86_64)
@@ -164,4 +160,3 @@
     ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Werror
   else
     ghc-options: -threaded -rtsopts -with-rtsopts=-N
-  default-language: Haskell2010
diff --git a/src/Language/Bond/Codegen/Cpp/ApplyOverloads.hs b/src/Language/Bond/Codegen/Cpp/ApplyOverloads.hs
--- a/src/Language/Bond/Codegen/Cpp/ApplyOverloads.hs
+++ b/src/Language/Bond/Codegen/Cpp/ApplyOverloads.hs
@@ -33,8 +33,7 @@
                const ::bond::bonded< #{qualifiedName}>& value);
 
     #{extern}template #{attr}
-    bool Apply(const ::bond::InitSchemaDef& transform,
-               const #{qualifiedName}& value);
+    bool Apply< #{qualifiedName}>(const ::bond::InitSchemaDef& transform);
 
     #{extern}template #{attr}
     bool Apply(const ::bond::Null& transform,
diff --git a/src/Language/Bond/Codegen/Cpp/Grpc_cpp.hs b/src/Language/Bond/Codegen/Cpp/Grpc_cpp.hs
deleted file mode 100644
--- a/src/Language/Bond/Codegen/Cpp/Grpc_cpp.hs
+++ /dev/null
@@ -1,33 +0,0 @@
--- Copyright (c) Microsoft. All rights reserved.
--- Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-{-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-}
-
-module Language.Bond.Codegen.Cpp.Grpc_cpp (grpc_cpp) where
-
-import Data.Monoid
-import Prelude
-import Data.Text.Lazy (Text)
-import Text.Shakespeare.Text
-import Language.Bond.Syntax.Types
-import Language.Bond.Codegen.TypeMapping
-import Language.Bond.Codegen.Util
-import qualified Language.Bond.Codegen.Cpp.Util as CPP
-
--- | Codegen template for generating /base_name/_grpc.cpp containing
--- definitions of helper functions and schema metadata static variables.
-grpc_cpp :: MappingContext -> String -> [Import] -> [Declaration] -> (String, Text)
-grpc_cpp cpp file _imports declarations = ("_grpc.cpp", [lt|
-#include "#{file}_reflection.h"
-#include "#{file}_grpc.h"
-
-#{CPP.openNamespace cpp}
-    #{doubleLineSepEnd 1 statics declarations}
-#{CPP.closeNamespace cpp}
-|])
-  where
-    -- definitions of Schema statics for non-generic services
-    statics s@Service {..} =
-        if null declParams then CPP.schemaMetadata cpp s else mempty
-
-    statics _ = mempty
diff --git a/src/Language/Bond/Codegen/Cpp/Grpc_h.hs b/src/Language/Bond/Codegen/Cpp/Grpc_h.hs
deleted file mode 100644
--- a/src/Language/Bond/Codegen/Cpp/Grpc_h.hs
+++ /dev/null
@@ -1,237 +0,0 @@
--- Copyright (c) Microsoft. All rights reserved.
--- Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-{-# LANGUAGE QuasiQuotes, OverloadedStrings, RecordWildCards #-}
-
-module Language.Bond.Codegen.Cpp.Grpc_h (grpc_h) where
-
-import System.FilePath
-import Data.Maybe (isNothing)
-import Data.Monoid
-import Prelude
-import qualified Data.Text.Lazy as L
-import Data.Text.Lazy.Builder
-import Text.Shakespeare.Text
-import Language.Bond.Util
-import Language.Bond.Syntax.Types
-import Language.Bond.Codegen.Util
-import Language.Bond.Codegen.TypeMapping
-import qualified Language.Bond.Codegen.Cpp.Util as CPP
-
-
--- | Codegen template for generating /base_name/_grpc.h containing declarations of
--- of service interface and proxy.
-grpc_h :: Maybe String -> MappingContext -> String -> [Import] -> [Declaration] -> (String, L.Text)
-grpc_h export_attribute cpp file imports declarations = ("_grpc.h", [lt|
-#pragma once
-
-#include "#{file}_reflection.h"
-#include "#{file}_types.h"
-#{newlineSep 0 includeImport imports}
-#{includeBondReflection}
-#include <bond/core/bonded.h>
-#include <bond/ext/grpc/reflection.h>
-#include <bond/ext/grpc/detail/client.h>
-#include <bond/ext/grpc/detail/service.h>
-
-#include <boost/optional/optional.hpp>
-#include <functional>
-#include <memory>
-
-#{CPP.openNamespace cpp}
-#{doubleLineSep 1 grpc declarations}
-
-#{CPP.closeNamespace cpp}
-
-|])
-  where
-    includeImport (Import path) = [lt|#include "#{dropExtension (slashForward path)}_grpc.h"|]
-
-    idl = MappingContext idlTypeMapping [] [] []
-
-    cppType = getTypeName cpp
-
-    payload = maybe "void" cppType
-
-    bonded mt = bonded' (payload mt)
-      where
-        bonded' params =  [lt|::bond::bonded<#{padLeft}#{params}>|]
-          where
-            paramsText = toLazyText params
-            padLeft = if L.head paramsText == ':' then [lt| |] else mempty
-
-    includeBondReflection =
-      if usesBondVoid then [lt|#include <bond/core/bond_reflection.h>|] else mempty
-      where usesBondVoid = any declUses declarations
-            declUses Service {serviceMethods = methods} = any methodUses methods
-            declUses _ = False
-            methodUses Function {methodInput = input} = isNothing (methodTypeToMaybe input)
-            methodUses Event {} = True
-
-    grpc s@Service{..} = [lt|
-#{template}struct #{declName} final
-{
-    struct Schema
-    {
-        #{export_attr}static const ::bond::Metadata metadata;
-
-        #{newlineSep 2 methodMetadata serviceMethods}
-
-        public: struct service
-        {
-            #{newlineSep 3 (uncurry methodTemplate) (zip serviceMethods uniqueMethodTemplateStructNames)}
-        };
-
-        private: typedef boost::mpl::list<> methods0;
-        #{newlineSep 2 pushMethod indexedMethods}
-
-        public: typedef #{typename}methods#{length serviceMethods}::type methods;
-
-        #{constructor}
-    };
-
-    class #{proxyName} : public ::bond::ext::grpc::detail::client
-    {
-    public:
-        using ::bond::ext::grpc::detail::client::client;
-
-        #{doubleLineSep 2 publicProxyMethodDecl serviceMethods}
-
-    private:
-        #{newlineSep 2 privateProxyMethodDecl serviceMethods}
-    };
-
-    class #{serviceName} : public ::bond::ext::grpc::detail::service
-    {
-    public:
-        explicit #{serviceName}(const ::bond::ext::grpc::Scheduler& scheduler)
-            : ::bond::ext::grpc::detail::service(
-                scheduler,
-                {
-                    #{commaLineSep 5 serviceMethodName serviceMethods}
-                })
-        {}
-
-        #{newlineSep 2 serviceVirtualMethod serviceMethods}
-
-    private:
-        void start() override
-        {
-            _data.emplace(*this);
-        }
-
-        struct data
-        {
-            explicit data(#{serviceName}& s)
-                : _s(s)
-            {}
-
-            #{serviceName}& _s;
-            #{newlineSep 3 serviceDataMember serviceMethodsWithIndex}
-        };
-
-        ::boost::optional<data> _data;
-    };
-};
-
-#{onlyTemplate $ CPP.schemaMetadata cpp s}
-|]
-      where
-        template = CPP.template s
-        onlyTemplate x = if null declParams then mempty else x
-        onlyNonTemplate x = if null declParams then x else mempty
-        typename = onlyTemplate [lt|typename |]
-
-        export_attr = onlyNonTemplate $ optional (\a -> [lt|#{a}
-        |]) export_attribute
-
-        methodMetadataVar m = [lt|s_#{methodName m}_metadata|]
-
-        methodMetadata m =
-            [lt|private: #{export_attr}static const ::bond::Metadata #{methodMetadataVar m};|]
-
-        -- reversed list of method names zipped with indexes
-        indexedMethods :: [(String, Int)]
-        indexedMethods = zipWith ((,) . methodName) (reverse serviceMethods) [0..]
-
-        pushMethod (method, i) =
-            [lt|private: typedef #{typename}boost::mpl::push_front<methods#{i}, #{typename}service::#{method}>::type methods#{i + 1};|]
-
-        -- constructor, generated only for service templates
-        constructor = onlyTemplate [lt|Schema()
-        {
-            // Force instantiation of template statics
-            (void)metadata;
-            #{newlineSep 3 static serviceMethods}
-        }|]
-          where
-            static m = [lt|(void)#{methodMetadataVar m};|]
-
-        -- unique names for each of the MethodTemplate derived structs that
-        -- we need to generate in the same order as serviceMethods.
-        uniqueMethodTemplateStructNames :: [String]
-        uniqueMethodTemplateStructNames = uniqueNames (map (\n -> n ++ "_type") methodNames) reservedNames
-          where
-            methodNames = map methodName serviceMethods
-            reservedNames = methodTemplateReservedNames ++ methodNames
-            -- methodTemplateReservedNames are names used in ::bond::reflection::MethodTemplate<>
-            methodTemplateReservedNames = ["MethodTemplate", "service_type", "input_type", "result_type", "metadata", "method"]
-
-        methodTemplate :: Method -> String -> L.Text
-        methodTemplate m methodTemplateStructName = [lt|typedef struct #{methodTemplateStructName} : ::bond::ext::grpc::reflection::MethodTemplate<#{declName}, #{payload $ methodTypeToMaybe (methodInput m)}, #{resultType m}, &#{methodMetadataVar m}> {} #{methodName m};|]
-
-        proxyName = "Client" :: String
-        serviceName = "Service" :: String
-
-        serviceMethodsWithIndex :: [(Integer,Method)]
-        serviceMethodsWithIndex = zip [0..] serviceMethods
-
-        publicProxyMethodDecl Function{methodInput = Void, ..} = [lt|void Async#{methodName}(const ::std::function<void(::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>)>& cb, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), cb);
-        }
-        ::std::future<::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>> Async#{methodName}(::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            return ::bond::ext::grpc::detail::client::dispatch<#{payload (methodTypeToMaybe methodResult)}>(_m#{methodName}, std::move(context));
-        }|]
-        publicProxyMethodDecl Function{..} = [lt|void Async#{methodName}(const #{bonded (methodTypeToMaybe methodInput)}& request, const ::std::function<void(::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>)>& cb, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), cb, request);
-        }
-        std::future<::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>> Async#{methodName}(const #{bonded (methodTypeToMaybe methodInput)}& request, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            return ::bond::ext::grpc::detail::client::dispatch<#{payload (methodTypeToMaybe methodResult)}>(_m#{methodName}, std::move(context), request);
-        }
-        void Async#{methodName}(const #{payload (methodTypeToMaybe methodInput)}& request, const ::std::function<void(::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>)>& cb, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), cb, request);
-        }
-        ::std::future<::bond::ext::grpc::unary_call_result<#{payload (methodTypeToMaybe methodResult)}>> Async#{methodName}(const #{payload (methodTypeToMaybe methodInput)}& request, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            return ::bond::ext::grpc::detail::client::dispatch<#{payload (methodTypeToMaybe methodResult)}>(_m#{methodName}, std::move(context), request);
-        }|]
-        publicProxyMethodDecl Event{methodInput = Void, ..} = [lt|void Async#{methodName}(::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), {});
-        }|]
-        publicProxyMethodDecl Event{..} = [lt|void Async#{methodName}(const #{bonded (methodTypeToMaybe methodInput)}& request, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), {}, request);
-        }
-        void Async#{methodName}(const #{payload (methodTypeToMaybe methodInput)}& request, ::std::shared_ptr<::grpc::ClientContext> context = {})
-        {
-            ::bond::ext::grpc::detail::client::dispatch(_m#{methodName}, std::move(context), {}, request);
-        }|]
-
-        privateProxyMethodDecl f = [lt|const ::bond::ext::grpc::detail::client::Method _m#{methodName f}{ ::bond::ext::grpc::detail::client::make_method("/#{getDeclTypeName idl s}/#{methodName f}") };|]
-
-        serviceMethodName f = [lt|"/#{getDeclTypeName idl s}/#{methodName f}"|]
-
-        serviceDataMember (index,f) = [lt|::bond::ext::grpc::detail::service::Method _m#{index}{ _s, #{index}, ::bond::ext::grpc::detail::service::make_callback(&#{serviceName}::#{methodName f}, _s) };|]
-
-        serviceVirtualMethod f = [lt|virtual void #{methodName f}(::bond::ext::grpc::unary_call<#{payload $ methodTypeToMaybe $ methodInput f}, #{resultType f}>) = 0;|]
-
-        resultType Function{..} = payload (methodTypeToMaybe methodResult)
-        resultType Event{} = "::bond::reflection::nothing"
-
-    grpc _ = mempty
diff --git a/src/Language/Bond/Codegen/Cpp/Types_h.hs b/src/Language/Bond/Codegen/Cpp/Types_h.hs
--- a/src/Language/Bond/Codegen/Cpp/Types_h.hs
+++ b/src/Language/Bond/Codegen/Cpp/Types_h.hs
@@ -39,7 +39,7 @@
 #{newlineBeginSep 0 includeHeader userHeaders}
 #include <bond/core/bond_version.h>
 
-#if BOND_VERSION < 0x0900
+#if BOND_VERSION < 0x0b00
 #error This file was generated by a newer version of the Bond compiler and is incompatible with your version of the Bond library.
 #endif
 
diff --git a/src/Language/Bond/Codegen/Cs/Grpc_cs.hs b/src/Language/Bond/Codegen/Cs/Grpc_cs.hs
deleted file mode 100644
--- a/src/Language/Bond/Codegen/Cs/Grpc_cs.hs
+++ /dev/null
@@ -1,241 +0,0 @@
--- Copyright (c) Microsoft. All rights reserved.
--- Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-{-# LANGUAGE OverloadedStrings, QuasiQuotes, RecordWildCards #-}
-
-module Language.Bond.Codegen.Cs.Grpc_cs (
-  grpc_cs)
-where
-
-import Data.Monoid
-import qualified Data.Text.Lazy as L
-import qualified Language.Bond.Codegen.Cs.Util as CS
-import Language.Bond.Codegen.TypeMapping
-import Language.Bond.Codegen.Util
-import Language.Bond.Syntax.Types hiding (methodTypeToMaybe)
-import Language.Bond.Util
-import Prelude
-import Text.Shakespeare.Text
-
--- | Represents a parameter in an abstract server method.
---
--- This data definition would be in the where clause of grpc_cs if data
--- definitions were permitted in where clauses.
-data CsServerMethodParam = CsServerMethodParam { name :: L.Text, csType :: L.Text }
-
--- | Generates a C# parameter declaration for a server method parameter.
-csServerParamDecl :: CsServerMethodParam -> L.Text
-csServerParamDecl (CsServerMethodParam {..}) = [lt|#{csType} #{name}|]
-
--- | Contains splicable text for a client method's first parameter. Create
--- one of these with the function csClientRequestParam. Some kinds of
--- methods don't need a first param, so some of the record's fields may be
--- empty. If non-empty, the correct comma and space are included so this
--- text can just be spliced in.
---
--- This data definition would be in the where clause of grpc_cs if data
--- definitions were permitted in where clauses.
-data CsClientRequestParam = CsClientRequestParam
-  { bareParam :: L.Text -- bare param declaration: what the caller passes in, if applicable
-  , messageParam :: L.Text -- param declaration wrapped in an IMessage
-  , toMessage :: L.Text -- code to create an IMessage for the request
-  , forwardMessageParam :: L.Text -- code to forward the IMessage param on to the CallInvoker
-  }
-
--- | Codegen template for generating code containing declarations of
--- of services including proxies and services files for gRPC integration.
-grpc_cs :: MappingContext -> String -> [Import] -> [Declaration] -> (String, L.Text)
-grpc_cs cs _ _ declarations = ("_grpc.cs", [lt|
-#{CS.disableCscWarnings}
-#{CS.disableReSharperWarnings}
-
-namespace #{csNamespace}
-{
-    using System.Collections.Generic;
-
-    #{doubleLineSep 1 grpc declarations}
-} // #{csNamespace}
-|])
-  where
-    csNamespace = sepBy "." toText $ getNamespace cs
-    idl = MappingContext idlTypeMapping [] [] []
-
-    grpc s@Service{..} = [lt|#{CS.typeAttributes cs s}public static class #{declName}#{generics} #{genericsWhere}
-    {
-        static readonly string ServiceName = "#{getDeclTypeName idl s}";
-
-        #{doubleLineSep 2 methodDeclaration serviceMethods}
-
-        public abstract class #{declName}Base
-        {
-            #{doubleLineSep 3 serverBaseMethods serviceMethods}
-        }
-
-        public class #{declName}Client : global::Grpc.Core.ClientBase<#{declName}Client>
-        {
-            public #{declName}Client(global::Grpc.Core.Channel channel) : base(channel)
-            {
-            }
-
-            public #{declName}Client(global::Grpc.Core.CallInvoker callInvoker) : base(callInvoker)
-            {
-            }
-
-            protected #{declName}Client() : base()
-            {
-            }
-
-            protected #{declName}Client(global::Grpc.Core.ClientBase.ClientBaseConfiguration configuration) : base(configuration)
-            {
-            }
-
-            #{doubleLineSep 3 clientMethods serviceMethods}
-
-            protected override #{declName}Client NewInstance(global::Grpc.Core.ClientBase.ClientBaseConfiguration configuration)
-            {
-                return new #{declName}Client(configuration);
-            }
-        }
-
-        public static global::Grpc.Core.ServerServiceDefinition BindService(#{declName}Base serviceImpl)
-        {
-            return global::Grpc.Core.ServerServiceDefinition.CreateBuilder()
-                    #{newlineSep 5 serviceMethodBuilder serviceMethods}
-                    .Build();
-        }
-    }
-|]
-      where
-        methodNames = map methodName serviceMethods
-
-        uniqImplName name = uniqueName (name ++ "_impl") methodNames
-
-        csTypeOf Void = "global::Bond.Void"
-        csTypeOf (Unary t) = getTypeName cs t
-        csTypeOf (Streaming t) = getTypeName cs t
-
-        csRequestTypeName (Function {..}) = csTypeOf methodInput
-        csRequestTypeName (Event {..}) = csTypeOf methodInput
-
-        csResponseTypeName (Function {..}) = csTypeOf methodResult
-        csResponseTypeName Event{} = csTypeOf Void
-      
-        messageVoid = [lt|global::Bond.Grpc.IMessage<global::Bond.Void>|]
-
-        messageOf :: Type -> L.Text
-        messageOf t = [lt|global::Bond.Grpc.IMessage<#{getTypeName cs t}>|]
-
-        methodTypeEnum :: Method -> L.Text
-        methodTypeEnum (Function {..}) = case (methodResult, methodInput) of
-            (Streaming _, Streaming _) -> [lt|global::Grpc.Core.MethodType.DuplexStreaming|]
-            (Streaming _, _)           -> [lt|global::Grpc.Core.MethodType.ServerStreaming|]
-            (_, Streaming _)           -> [lt|global::Grpc.Core.MethodType.ClientStreaming|]
-            _                          -> [lt|global::Grpc.Core.MethodType.Unary|]
-        methodTypeEnum (Event {..}) = case methodInput of
-            Streaming _ -> error ("Unexpected event '" ++ methodName ++ "' with Streaming parameter") -- the parser should have rejected this
-            _           -> [lt|global::Grpc.Core.MethodType.Unary|]
-
-        generics = angles $ sepBy ", " paramName declParams
-
-        genericsWhere = sepBy " " addWhere declParams
-          where
-            addWhere a = [lt|where #{paramName a} : class|]
-
-        methodDeclaration m = [lt|static readonly global::Grpc.Core.Method<global::Bond.Grpc.IMessage<#{csRequestTypeName m}>, global::Bond.Grpc.IMessage<#{csResponseTypeName m}>> Method_#{methodName m} = new global::Grpc.Core.Method<global::Bond.Grpc.IMessage<#{csRequestTypeName m}>, global::Bond.Grpc.IMessage<#{csResponseTypeName m}>>(
-            #{methodTypeEnum m},
-            ServiceName,
-            "#{methodName m}",
-            global::Bond.Grpc.Marshaller<#{csRequestTypeName m}>.Instance,
-            global::Bond.Grpc.Marshaller<#{csResponseTypeName m}>.Instance);|]
-
-        serverMethodParams :: MethodType -> MethodType -> [CsServerMethodParam]
-        serverMethodParams reqType respType = (forRequest reqType) ++ (forResponse respType) ++ context
-          where
-            forRequest Void = [(CsServerMethodParam  [lt|request|] messageVoid)]
-            forRequest (Unary t) = [(CsServerMethodParam [lt|request|] [lt|#{messageOf t}|])]
-            forRequest (Streaming t) = [(CsServerMethodParam [lt|requests|] [lt|Grpc.Core.IAsyncStreamReader<#{messageOf t}>|])]
-            forResponse Void = []
-            forResponse (Unary _) = []
-            forResponse (Streaming t) = [(CsServerMethodParam [lt|responses|] [lt|Grpc.Core.IAsyncStreamWriter<#{messageOf t}>|])]
-            context = [(CsServerMethodParam [lt|context|] [lt|global::Grpc.Core.ServerCallContext|])]
-
-        -- | For functions (not events), given the result type, compute the
-        -- C# abstract method return type.
-        csServerFunctionReturn :: MethodType -> L.Text
-        csServerFunctionReturn Void = [lt|global::System.Threading.Tasks.Task<#{messageVoid}>|]
-        csServerFunctionReturn (Unary t) = [lt|global::System.Threading.Tasks.Task<#{messageOf t}>|]
-        csServerFunctionReturn (Streaming _) = [lt|global::System.Threading.Tasks.Task|]
-
-        serverBaseMethods Function{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public abstract #{csServerFunctionReturn methodResult} #{methodName}(#{csParams});|]
-          where params = serverMethodParams methodInput methodResult
-                csParams = commaSep csServerParamDecl params
-
-        serverBaseMethods Event{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public abstract global::System.Threading.Tasks.Task #{methodName}(#{csParams});
-
-            internal global::System.Threading.Tasks.Task<#{messageVoid}> #{uniqImplName methodName}(#{csParams}) {
-                return global::Bond.Grpc.Internal.NothingCallHandler.Handle(#{handlerArgs});
-            }|]
-          where params = serverMethodParams methodInput Void
-                csParams = commaSep csServerParamDecl params
-                handlerArgs = commaSep id ((L.pack methodName):(map name params))
-
-        -- | For functions (not events), given the input and result types,
-        -- compute the C# client method return type.
-        csClientFunctionReturn :: MethodType -> MethodType -> L.Text
-        csClientFunctionReturn (Streaming input) (Streaming result) = [lt|global::Grpc.Core.AsyncDuplexStreamingCall<#{messageOf input}, #{messageOf result}>|]
-        csClientFunctionReturn (Streaming input) (Unary result) = [lt|global::Grpc.Core.AsyncClientStreamingCall<#{messageOf input}, #{messageOf result}>|]
-        csClientFunctionReturn _ (Streaming result) = [lt|global::Grpc.Core.AsyncServerStreamingCall<#{messageOf result}>|]
-        csClientFunctionReturn _ (Unary result) = [lt|global::Grpc.Core.AsyncUnaryCall<#{messageOf result}>|]
-        csClientFunctionReturn _ Void = [lt|global::Grpc.Core.AsyncUnaryCall<#{messageVoid}>|]
-
-        -- | Given the input type, compute the client method parameter.
-        csClientRequestParam :: MethodType -> CsClientRequestParam
-        csClientRequestParam Void = CsClientRequestParam
-          { bareParam = mempty
-          , messageParam = [lt|#{messageVoid} request, |]
-          , toMessage = [lt|global::Bond.Grpc.Message.Void, |]
-          , forwardMessageParam = [lt|, request|] }
-        csClientRequestParam (Unary t) = CsClientRequestParam
-          { bareParam = [lt|#{getTypeName cs t} request, |]
-          , messageParam = [lt|#{messageOf t} request, |]
-          , toMessage = [lt|global::Bond.Grpc.Message.From(request), |]
-          , forwardMessageParam = [lt|, request|] }
-        csClientRequestParam (Streaming _) = CsClientRequestParam
-          { bareParam = mempty
-          , messageParam = mempty
-          , toMessage = mempty
-          , forwardMessageParam = mempty }
-
-        -- | Given the input and result types, compute the call invoker needed.
-        clientCallInvoker :: MethodType -> MethodType -> L.Text
-        clientCallInvoker (Streaming _) (Streaming _) = [lt|AsyncDuplexStreamingCall|]
-        clientCallInvoker (Streaming _) (Unary _)     = [lt|AsyncClientStreamingCall|]
-        clientCallInvoker (Unary _) (Streaming _)     = [lt|AsyncServerStreamingCall|]
-        clientCallInvoker _ _                         = [lt|AsyncUnaryCall|]
-
-        clientMethods Function{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public virtual #{csClientFunctionReturn methodInput methodResult} #{methodName}Async(#{bareParam requestParam}global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-            {
-                return #{methodName}Async(#{toMessage requestParam}new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
-            }
-
-            #{CS.schemaAttributes 3 methodAttributes}public virtual #{csClientFunctionReturn methodInput methodResult} #{methodName}Async(#{messageParam requestParam}global::Grpc.Core.CallOptions options)
-            {
-                return CallInvoker.#{clientCallInvoker methodInput methodResult}(Method_#{methodName}, null, options#{forwardMessageParam requestParam});
-            }|]
-          where requestParam = csClientRequestParam methodInput
-
-        clientMethods Event{..} = [lt|#{CS.schemaAttributes 3 methodAttributes}public virtual void #{methodName}Async(#{bareParam requestParam}global::Grpc.Core.Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-            {
-                #{methodName}Async(#{toMessage requestParam}new global::Grpc.Core.CallOptions(headers, deadline, cancellationToken));
-            }
-
-            #{CS.schemaAttributes 3 methodAttributes}public virtual void #{methodName}Async(#{messageParam requestParam}global::Grpc.Core.CallOptions options)
-            {
-                global::Bond.Grpc.Internal.NothingCallInvoker.NothingCall(CallInvoker, Method_#{methodName}, null, options#{forwardMessageParam requestParam});
-            }|]
-          where requestParam = csClientRequestParam methodInput
-
-        serviceMethodBuilder Function{..} = [lt|.AddMethod(Method_#{methodName}, serviceImpl.#{methodName})|]
-        serviceMethodBuilder Event{..} = [lt|.AddMethod(Method_#{methodName}, serviceImpl.#{uniqImplName methodName})|]
-
-    grpc _ = mempty
diff --git a/src/Language/Bond/Codegen/Cs/Util.hs b/src/Language/Bond/Codegen/Cs/Util.hs
--- a/src/Language/Bond/Codegen/Cs/Util.hs
+++ b/src/Language/Bond/Codegen/Cs/Util.hs
@@ -16,7 +16,8 @@
 import Data.Int (Int64)
 import Data.Monoid
 import Prelude
-import Data.Text.Lazy (Text)
+import Data.Text.Lazy (Text, isPrefixOf)
+import Data.Text.Lazy.Builder (toLazyText)
 import Text.Shakespeare.Text
 import Paths_bond (version)
 import Data.Version (showVersion)
@@ -112,15 +113,20 @@
     constraint (TypeParam _ Nothing) = mempty
     constraint (TypeParam name (Just Value)) = [lt|where #{name} : struct|]
 
+isImmutableCollection :: MappingContext -> Type -> Bool
+isImmutableCollection cs t = [lt|System.Collections.Immutable.Immutable|] `isPrefixOf` toLazyText (getInstanceTypeName cs t)
+
 -- Initial value for C# field/property or Nothing if C# implicit default is OK
 defaultValue :: MappingContext -> Field -> Maybe Text
 defaultValue cs Field {fieldDefault = Nothing, ..} = implicitDefault fieldType
   where
     newInstance t = Just [lt|new #{getInstanceTypeName cs t}()|]
+    staticEmptyField t = Just [lt|#{getInstanceTypeName cs t}.Empty|]
     implicitDefault (BT_Bonded t) = Just [lt|global::Bond.Bonded<#{getTypeName cs t}>.Empty|]
     implicitDefault t@(BT_TypeParam _) = Just [lt|global::Bond.GenericFactory.Create<#{getInstanceTypeName cs t}>()|]
     implicitDefault t@BT_Blob = newInstance t
     implicitDefault t@(BT_UserDefined a@Alias {..} args)
+        | isImmutableCollection cs t = staticEmptyField t
         | customAliasMapping cs a = newInstance t
         | otherwise = implicitDefault $ resolveAlias a args
     implicitDefault t
diff --git a/src/Language/Bond/Codegen/Templates.hs b/src/Language/Bond/Codegen/Templates.hs
--- a/src/Language/Bond/Codegen/Templates.hs
+++ b/src/Language/Bond/Codegen/Templates.hs
@@ -41,14 +41,11 @@
     , apply_h
     , apply_cpp
     ,  Protocol(..)
-    , grpc_h
-    , grpc_cpp
       -- ** C#
     , FieldMapping(..)
     , StructMapping(..)
     , ConstructorOptions(..)
     , types_cs
-    , grpc_cs
       -- ** Java
     , JavaFieldMapping(..)
     , class_java
@@ -63,10 +60,7 @@
 import Language.Bond.Codegen.Cpp.Reflection_h
 import Language.Bond.Codegen.Cpp.Types_cpp
 import Language.Bond.Codegen.Cpp.Types_h
-import Language.Bond.Codegen.Cpp.Grpc_cpp
-import Language.Bond.Codegen.Cpp.Grpc_h
 import Language.Bond.Codegen.Cs.Types_cs
-import Language.Bond.Codegen.Cs.Grpc_cs
 import Language.Bond.Codegen.Java.Class_java
 import Language.Bond.Codegen.Java.Enum_java
 -- redundant imports for haddock
diff --git a/tests/TestMain.hs b/tests/TestMain.hs
--- a/tests/TestMain.hs
+++ b/tests/TestMain.hs
@@ -124,11 +124,6 @@
                     [ "c++"
                     , "--export-attribute=DllExport"
                     ]
-                    "service"
-                , verifyExportsCodegen
-                    [ "c++"
-                    , "--export-attribute=DllExport"
-                    ]
                     "with_enum_header"
                 ]
             , verifyCodegen
@@ -136,20 +131,6 @@
                 , "--namespace=tests=nsmapped"
                 ]
                 "basic_types_nsmapped"
-            , testGroup "Grpc"
-                [ verifyCppGrpcCodegen
-                    [ "c++"
-                    ]
-                    "service"
-                , verifyCppGrpcCodegen
-                    [ "c++"
-                    ]
-                    "generic_service"
-                , verifyCppGrpcCodegen
-                    [ "c++"
-                    ]
-                    "service_attributes"
-                ]
             ]
         , testGroup "C#"
             [ verifyCsCodegen "attributes"
@@ -163,6 +144,16 @@
             , verifyCsCodegen "inheritance"
             , verifyCsCodegen "aliases"
             , verifyCsCodegen "complex_inheritance"
+            , verifyCodegen
+                [ "c#"
+                , "--using=ImmutableArray=System.Collections.Immutable.ImmutableArray<{0}>"
+                , "--using=ImmutableList=System.Collections.Immutable.ImmutableList<{0}>"
+                , "--using=ImmutableHashSet=System.Collections.Immutable.ImmutableHashSet<{0}>"
+                , "--using=ImmutableSortedSet=System.Collections.Immutable.ImmutableSortedSet<{0}>"
+                , "--using=ImmutableDictionary=System.Collections.Immutable.ImmutableDictionary<{0},{1}>"
+                , "--using=ImmutableSortedDictionary=System.Collections.Immutable.ImmutableSortedDictionary<{0},{1}>"
+                ]
+                "immutable_collections"
             , verifyCodegenVariation
                 [ "c#"
                 , "--preview-constructor-parameters"
@@ -199,24 +190,6 @@
                 ]
                 "empty_struct"
                 "constructor-parameters"
-            , testGroup "Grpc"
-                [ verifyCsGrpcCodegen
-                    [ "c#"
-                    ]
-                    "service"
-                , verifyCsGrpcCodegen
-                    [ "c#"
-                    ]
-                    "generic_service"
-                , verifyCsGrpcCodegen
-                    [ "c#"
-                    ]
-                    "service_attributes"
-                , verifyCsGrpcCodegen
-                    [ "c#"
-                    ]
-                    "streaming"
-                ]
             ]
         , testGroup "Java"
             [ verifyJavaCodegen "attributes"
diff --git a/tests/Tests/Codegen.hs b/tests/Tests/Codegen.hs
--- a/tests/Tests/Codegen.hs
+++ b/tests/Tests/Codegen.hs
@@ -8,11 +8,9 @@
     ( verifyCodegen
     , verifyCodegenVariation
     , verifyCppCodegen
-    , verifyCppGrpcCodegen
     , verifyApplyCodegen
     , verifyExportsCodegen
     , verifyCsCodegen
-    , verifyCsGrpcCodegen
     , verifyJavaCodegen
     ) where
 
@@ -85,35 +83,6 @@
         [ reflection_h export_attribute
         , types_h export_attribute header enum_header allocator alloc_ctors_enabled type_aliases_enabled scoped_alloc_enabled
         ]
-
-verifyCppGrpcCodegen :: [String] -> FilePath -> TestTree
-verifyCppGrpcCodegen args baseName =
-    testGroup baseName $
-        map (verifyFile options baseName (cppExpandAliases (type_aliases_enabled options) cppTypeMapping) "") templates
-  where
-    options = processOptions args
-    templates =
-        [ grpc_h (export_attribute options)
-        , grpc_cpp
-        , types_cpp
-        ]
-
-verifyCsGrpcCodegen :: [String] -> FilePath -> TestTree
-verifyCsGrpcCodegen args baseName =
-    testGroup baseName $
-        map (verifyFile (processOptions args) baseName csTypeMapping "")
-            [ grpc_cs
-            , types_cs Class (fieldMapping (processOptions args)) (constructorOptions (processOptions args))
-            ]
-  where
-    fieldMapping Cs {..} = if readonly_properties
-        then ReadOnlyProperties
-        else if fields
-             then PublicFields
-             else Properties
-    constructorOptions Cs {..} = if constructor_parameters
-        then ConstructorParameters
-        else DefaultWithProtectedBase
 
 verifyFiles :: Options -> FilePath -> FilePath -> [TestTree]
 verifyFiles options baseName variation =
