Advantages of message based web services

Demis Bellot edited this page Oct 25, 2016 · 29 revisions

This page has moved to

This is in response to a recent question from mailing group:

It seems like ServiceStack is designed for use primarily in a greenfield 
SOA implementation where the technology environment is quite homogeneous, 
and more or less the same people have ownership of the servers and all the clients.  
Is that correct?

ServiceStack's message-based design is optimal for the design of any remote service. We believe .NET has never gotten web services right, which was the inspiration for starting ServiceStack. If .NET was lucky enough to have had someone like Martin Fowler (or just someone following his decade-old guidance) at the helm of the Microsoft Patterns & Practices and VS.NET tools teams from the start we would've likely been able to avoid the multiple replacement web service frameworks from Microsoft that .NET web service developers have endured over the years - and still haven't got right. This is unfortunate considering remote services are the most important APIs developers can create as they ultimately offer the highest-level of software re-use possible whilst remaining programatically composable.

Best-practices for remote services

Inspiration should've ideally been taken from Martin Fowler or from companies that have SOA ingrained in their DNA who have successfully run long-term evolving SOA solutions that have enabled rich and complex platforms. Amazon is a shining example of this, where even Steve Yegge admits it's the only thing they do better than Google. Where their relentless dedication to exposing SOA services over all their systems have enabled their industry leading EC2 and cloud services.

The Service API of Amazon's Web Services

If you look at an example of Amazons EC2 Web Service APIs you'll see a strong similarity with ServiceStack's approach where they accept a Request message and return a response message for all their services, e.g:

Example Request

Example Response

<AttachVolumeResponse xmlns="">

From this we can attest Amazon maintains a Request DTO named AttachVolume and a Response DTO named AttachVolumeResponse. This is the same design ServiceStack encourages and with some minor customisations the Request can be easily made to be more REST-ful with:

FormData: InstanceId=i-6058a509&Device=/dev/sdh&AUTHPARAMS

In-terms of accessibility and interoperability, ServiceStack 1-ups Amazon here since the same Request DTO can be populated with any combination of a Custom Route, QueryString, FormData or a POST'ed XML, JSON, JSV, SOAP 1.1/1.2 or ProtoBuf Request DTO payload. Although this is really inconsequential since both Amazon and ServiceStack also provide typed service clients so you're never required to manually construct the request by hand.

Messaging at Google

Although Amazon holds the SOA edge, Google, like Amazon also benefits from message-based design for nearly all their internal communications using their own Data Interchange Format - Protocol Buffers, which like JSON is both fast, compact and tolerant:

Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal RPC protocols and file formats.

A simple DSL is used to define their Protocol Buffer message DTOs:

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;

From this they use their protoc command-line utility to generate native types in C++, Java and Python, which like Amazon and ServiceStack, enables them to benefit from using an end-to-end, typed API.

Add a reference to ServiceStack.Plugins.ProtoBuf to enable @marcgravell's excellent implementation of Protocol Buffers: protobuf-net.

A Productivity Win

We've been building SOA systems like this with ServiceStack for years: the productivity boost you get from using typed, end-to-end, resilient, message-based API is unmatched. An example of this was having developed over 100+ Web Services for the Redis WebServices project in just 1 weekend. Others that have tried ServiceStack also agree its ease-of-development and "pit of success" design it promotes ultimately yields a productivity win - this positive sentiment is captured in @ServiceStack's favourites and throughout the mailing group.

The anatomy of a ServiceStack service

For normal services, ServiceStack is an invisible library i.e. it lets you implement your service in pure, untainted C# accepting any user-defined Request and lets you return any Response DTO without any regard to endpoints and formats. Any dependencies your services need can be declared as public properties and are automatically auto-wired on each request. A complete example of this is the self-contained Backbone TODO backend persisted using Redis.

In contrast with SOAP

By contrast we've witnessed .NET devs struggling to implement much fewer SOAP web services within the same timeframe, especially when they're fighting un-expected and unknown WCF interoperability issues. Not only is SOAP more verbose and slower, its less tolerant and version-able, it was never a good choice for the open web and is now effectively deprecated.

The many webservice frameworks of Microsoft

Unfortunately despite Microsoft having hosted Martin Fowler's respected Data Transfer Object and Service Gateway patterns on MSDN for years - none of their web frameworks have encouraged their use. Instead in .NET we've been forced to code against the multiple generation of replacement web service frameworks they've churned out over the years like .asmx, CSF, WCF, WCF/REST, WSE, WCF DataServices, RIA, MVC (escaping earlier cruft) and now WebApi. Each of these frameworks share the same mistake of mapping to C# methods, which we believe is a terrible idea for network services since it promotes chatty and brittle remote interfaces, that fail to facilitate the easy creation of SOA-like Apis.

Throughout all these generations of frameworks ServiceStack's underlying core IService interface has remained constant - with its simple Execute method:

public interface IService<T> {
    object Execute(T request);

Which we've simplified even further in the New API to just an empty marker interface:

public interface IService { }

Which lets you handle any HTTP Verb, as well as a 'Catch All' Any fall-back to handle any un-specified HTTP verbs, e.g:

public class MyService : IService 
     public Response Get(Request request){...}
     public Response Post(Request request){...}

     //Fallback for Anything else e.g DELETE, PUT, PATCH, OPTIONS, etc.
     public Response Any(Request request){...} 

It simply accepts any user-defined Request DTO and returns any Response DTO - that you're given complete freedom to create. If ever more customization/headers is needed you can return the decorated response inside a HttpResult or HttpError to maintain full control over the HTTP output.

Message APIs minimizes round-trips, creates fewer, more re-usable and extensible services

Messages APIs are naturally batchful and promote the development of coarse-grained service interfaces. This encourages fewer, more re-usable services that are better positioned for extensibility - this is a key benefit, since well-defined (i.e. non RPC/client-specific) back-end services tend to out live the UIs and clients that consume them.

This is illustrated in this example between the different style of services that WCF and ServiceStack encourages. Another example showcasing the differences is in many of jQuery's APIs that take in an array of key/value pairs, like $.ajax(). Imagine if every configuration permutation was a different or overloaded method? This gets unwieldy, very quickly. A coarse-grained interface enables richer functionality in a single call, whilst sharing the same well-tested code-path.

Code-first POCO's

Since it promotes clean, re-usable code, ServiceStack has always encouraged the use of code-first POCO's for just about everything. i.e. the same POCO can be used:

Leveraging different technologies whose functionality is built around POCO's offer un-precedented levels of re-use, reduces friction, promotes consistent, more usable and easier to rationale code-bases.

The case against mapping to method signatures

The programmer convenience and familiarity of using method signatures for Service APIs is just not worth what you give up:

It encourages developers to treat web services as just another method call even though they're millions of times slower, the different properties between service endpoints and C# methods highlight more of the short comings of this approach where in order to be able to evolve your services without friction, services should be both forward and backwards compatible - not fail-fast. When you evolve and refactor a C# method you have the opportunity to refactor all the call sites to meet the new method signature - whereas in a disconnected (and already deployed) client/server solution you don't, you need to support both old and new clients requests and the only way to do this cleanly whilst still maintaining the same code-path is to pass messages between them.

But the main disadvantage of method signature service APIs is that they mandate the use of code-gen in order to provide a typed client API. Using messages allows you to re-use generic service clients for all your service communications. This is how, even up to this day ServiceStack remains the only .NET framework to maintain a terse, (both sync and async), typed, end-to-end client libraries without any code-gen, e.g:

Todo createdTodo = client.Post(new Todo { Content = "New Todo", Order = 1 });

Code-gen'ing service clients is evil

Although a subject of another post we consider code-gen an arthritis that imposes undue friction to a project, it adds un-necessary build steps, increases compile times, forces lock-step deployment of client/server endpoints (usually requiring downtime), inhibits DRY/code re-use amongst code-gen types, has your domain logic binded to external moving types (that are outside of your control), are less resilient since code-gen types parse the entire payload - so unwanted breakages can occur on changes to un-used parts of the request or response.

The only way to maintain a succinct API that maps to method signatures without code-gen is to use dynamic. We're a fan of dynamic languages for most (fuzzy) development tasks like creating/binding UIs, html generation, scripting, etc. But we don't think they're optimal for creating evolving service APIs with - which stand to benefit most from statically typed annotations, compiler warnings and the refactoring support that statically typed languages can provide.

Twitter benefitting from Typed Services

After having rewrote their Ruby APIs in Scala, Twitter also comes to the same conclusion:

I would say about half of the productivity gain is purely because of accumulated technical debt in the search Rails stack. And the other half is that, as search has moved into a Service Oriented Architecture and exposes various APIs, static typing becomes a big convenience in enforcing coherency across all the systems. You can guarantee that your dataflow is more or less going to work, and focus on the functional aspects. Whereas for something like building a web page you don't want to recompile all the time, you don't really want to worry about whether in some edge condition you are going to get a type you didn't expect. But as we move into a light-weight Service Oriented Architecture model, static typing becomes a genuine productivity boon. And Scala gives you the same thing.

Advantages of Message-based designs

So in contrast to method signatures, message-based designs offer many advantages:

  • They're easy to version and evolve since you're freely able to add/remove functionality and properties without error
  • They're easy to route, chain and decorate through to different handlers and pipelines
  • They're easy to serialize and proxy through to remote services
  • They're easy to record, defer and replay - evident by ServiceStack's IMessaging API which can automatically drop one-way services into MQ's and have them executed inside an MQ Host, you get this functionality for free since the MQ host can re-use the same web service implementation. It works the other way too where you can supply a Url in the ReplyTo property to have the MQ response POST'ed to a ServiceStack HTTP Service.
  • They're easy to log, evident by ServiceStack's trivially simple but useful IRequestLogger service
  • They're easy to map and translate to and from domain models using convention and auto mappers
  • Ideal for concurrency as immutable messages are thread-safe and can be easily multi-plexed with their handlers over multiple threads.

All these properties make messages a better choice for distributed systems, where all this functionality can be achieved with generic solutions since it's much easier to pass around and serialize messages than method signature invocations.

Message designs are well known

Although none of these qualities are new, message-based designs have been very well known for decades and are used in many of the most highly respected real-time distributed technologies: including Erlang processes, Java's JMS, Scala's Actors, Go's go-routines, Dart's isolates, F#'s Mailboxes as well as in industrial strength Message Queues which (amongst many other benefits) provide deferred, durable and reliable execution - which are a strong force in most other platforms.

Messaging practically non-existant in .NET

They're just weak in .NET since Microsoft has an un-naturally strong influence over .NET developer mindshare and have been able to steer mainstream .NET into using SOAP Web Services at the expense of MQ's and message-based solutions. Our guess for this was because they've only had a poor, outdated MQ option in MSMQ and that the 1) right-click 'Add Service Reference' and 2) call a remote service like a c# method, demos very well.

This could change with the advent of Azure Service Bus if Microsoft devotes some attention into pointing mainstream .NET devs towards a messaging approach. Although with the imminent release of WebApi and Microsoft's full marketing force, army of employees and full-time developer advocates behind it, they will likely be once again successful into moving most of mainstream .NET onto yet another replacement web-service framework for all their remote communication needs - when often message-based / SOA designs provide a better fit.

For those interested in discovering advantages of MQ's and message-based designs and their abilities in enabling loosely coupled distributed systems, we recommend the excellent book from Martin Fowler's signature series - Enterprise Integration Patterns.

So is ServiceStack only suitable for homogeneous environments that control client / server?

This is fairly inaccurate considering ServiceStack's mission is close to the exact opposite: i.e. to encapsulate and empower your services logic and host them in the most accessible and re-usable ways possible on the most popular endpoints and formats. This is, after all what the core objectives of a service should be, i.e. to expose high-level functionality in the most accessible way and consume them in least-effort possible.

Excellent built-in support of HTTP on most open and popular formats

Not only do all ServiceStack services accept a Request DTO populated with any combination of Custom Routes, QueryString and HTML FormData. You can also POST the serialized Request DTO in any of the in-built formats: i.e. XML, JSON, JSV, SOAP 1.1/1.2, ProtoBuf (when enabled) or your own custom format. All services immediately support JSONP and its trivial to enable CORS on all services. Should you wish, you're also able to have all HTTP Verbs execute the same service.

Support is included for registering raw custom IHttpHandler's, Request / Response Filters and HttpResult/HttpError results - giving you a multitude of options to maintain full control over the entire HTTP Output - should you need to meet any extraneous external requirements.

Text serializers are fast, resilient and idiomatic

ServiceStack's JSON & JSV serializers are case-insensitive (i.e. supports both camelCase and PascalCase properties) and the 1-line below (already included in most Example templates) emits idiomatic camelCase JSON output:

ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

They're both very resilient and can withstand extreme versioning without error making it easy to consume 3rd party APIs

Your services can be consumed by more than just HTTP

Your services implementation can even be re-used inside any IMessageService hosts, which at this time includes support for Redis, InMemory and RCON hosts (with more to follow) and work has already begun to enable a fast tcp/IPC async pipeline between ServiceStack and node.js + Dart server processes. All these features actually make ServiceStack one of the most versatile and flexible web service frameworks in existance - enabling your services accessible in a myriad of different use-cases.

Most examples don't actually have .NET clients

This is also a peculiar assumption in light of the fact that most ServiceStack Examples (as seen on are actually Single Page Apps being consumed with Ajax clients (i.e. no .NET clients in sight).

The Backbone TODOs example shows how trivial it was to retrofit Backbone's REST service with a ServiceStack backend and the SocialBootstrapApi example show-cases an internet-ready Single Page Backbone App with Facebook, Twitter, HTML Form credentials, Basic Auth & Digest Auth, all enabled. It also makes use of ServiceStack's cross-platform node.js bundler for statically compiling, minifying and concatenating your websites .coffee, .js, .less, .sass and .css assets - and since it works headless and without .NET, is able to be used for non .NET projects as well.

.NET clients can benefit from a typed API

.NET clients do benefit from being able to re-use the same types you've defined your web services with, which in addition to pre-defined auto routes and generic service clients, is what enables the typed, end-to-end client gateways.

Just as consumable as any other web service

But even without this, ServiceStack services are just as consumable as any other web service framework since they're just pure DTOs serialized into the preferred Content-Type, with no additional bytes or wrappers added to the response. Different client examples in contrast:

The earlier typed API example of creating a new TODO in C#:

var client = new JsonServiceClient(baseUrl);
Todo createdTodo = client.Send<Todo>(new Todo { Content = "New Todo", Order = 1 });

Is like this in Dart (using the Dart JSON Client):

var client = new JsonClient(baseUrl);
client.todos({'content':'New Todo', 'order':1})
      .then((createdTodo) => ...);

Or in jQuery:

$.post(baseUrl + '/todos', {content:'New Todo', order:1}, 
     function(createdTodo) { ... }, 'json');

And you still have the option to consume all services in other Content-Types. Some languages may prefer to deal with XML - which can easily be accessed by adding the appropriate Accept and Content-Type headers.

What's the best way to expose our services to clients today?

What was SOAP's original vision?

Back in the W3C glory days, existed think-tanks who imagined a beautiful world were you could easily discover and connect to services through the magical properties of UDDI and WSDLs. However this pipe-dream never came to pass, the closest .NET got was the 'Add Service Reference' dialog ingrained in VS.NET - which we refer to internally as the technical-debt-creating-anti-pattern dialog :)

So how should we expose our services now?

The natural choice would be to just document your services' uniform HTTP Interface using XML or JSON REST APIs. This is a popular choice for many companies today, some good examples include StackOverflow and GitHub. This approach easily supports dynamic clients who are able to trivially consume JSON responses.

Native language client libraries

A more productive option for clients however would be to provide a native client library for each of the popular languages you wish to support. This is generally the approach of companies who really, really want to help you use their services - they tend to call their clients SDK's which abstract away the underlying connection transport behind optimal native language bindings. This is especially evident from companies whose business relies on the popular use of their APIs, like Amazon, Facebook and Windows Azure. This is an especially good idea if you want to support static languages (i.e. C# and Java) where having typed client libraries saves end-users from reverse engineering the types and API calls. It also saves them having to look up documentation since a lot of it can be inferred from the type info. ServiceStack's and Amazons convention of having ServiceName and ServiceNameResponse for each service also saves users from continually checking documentation to work out what the response of each service will be.

Packaging client libraries

In terms of packaging your client libraries, sticking a link to a zip file on your Websites APIs documentation page would be the easiest approach. It would be better if the zip file was a link to a master archive of a Github repository as you'll be able to accept bug fixes and usability tips from the community. Finally we believe the best way to make your client libraries available would be to host them in the target languages native package manager - letting end-users issue 1-command to automatically add it to their project, and another to easily update it when your service has changed.

NuGet is the new Add Service Reference

For .NET this means adding it to NuGet. If you use ServiceStack your package would just need to contain your types with a reference to ServiceStack.Client - which contains all ServiceStack's generic JSON, XML, JSV and SOAP 1.1/1.2 service clients. Add a reference to ServiceStack.Plugins.ProtoBuf if you want to support Protocol Buffers as well. One of the benefits of using ServiceStack is that all your types are already created since it's what you used to define your web services with!

  1. Getting Started

    1. Creating your first project
    2. Create Service from scratch
    3. Your first webservice explained
    4. Example Projects Overview
    5. Learning Resources
  2. Designing APIs

    1. ServiceStack API Design
    2. Designing a REST-ful service with ServiceStack
    3. Simple Customer REST Example
    4. How to design a Message-Based API
    5. Software complexity and role of DTOs
  3. Reference

    1. Order of Operations
    2. The IoC container
    3. Configuration and AppSettings
    4. Metadata page
    5. Rest, SOAP & default endpoints
    6. SOAP support
    7. Routing
    8. Service return types
    9. Customize HTTP Responses
    10. Customize JSON Responses
    11. Plugins
    12. Validation
    13. Error Handling
    14. Security
    15. Debugging
    16. JavaScript Client Library (ss-utils.js)
  4. Clients

    1. Overview
    2. C#/.NET client
      1. .NET Core Clients
    3. Add ServiceStack Reference
      1. C# Add Reference
      2. F# Add Reference
      3. VB.NET Add Reference
      4. Swift Add Reference
      5. Java Add Reference
    4. Silverlight client
    5. JavaScript client
      1. Add TypeScript Reference
    6. Dart Client
    7. MQ Clients
  5. Formats

    1. Overview
    2. JSON/JSV and XML
    3. HTML5 Report Format
    4. CSV Format
    5. MessagePack Format
    6. ProtoBuf Format
  6. View Engines 4. Razor & Markdown Razor

    1. Markdown Razor
  7. Hosts

    1. IIS
    2. Self-hosting
    3. Messaging
    4. Mono
  8. Security

    1. Authentication
    2. Sessions
    3. Restricting Services
    4. Encrypted Messaging
  9. Advanced

    1. Configuration options
    2. Access HTTP specific features in services
    3. Logging
    4. Serialization/deserialization
    5. Request/response filters
    6. Filter attributes
    7. Concurrency Model
    8. Built-in profiling
    9. Form Hijacking Prevention
    10. Auto-Mapping
    11. HTTP Utils
    12. Dump Utils
    13. Virtual File System
    14. Config API
    15. Physical Project Structure
    16. Modularizing Services
    17. MVC Integration
    18. ServiceStack Integration
    19. Embedded Native Desktop Apps
    20. Auto Batched Requests
    21. Versioning
    22. Multitenancy
  10. Caching

  11. Caching Providers

  12. HTTP Caching

  13. CacheResponse Attribute

  14. Cache Aware Clients

  15. Auto Query

  16. Overview

  17. Why Not OData

  18. AutoQuery RDBMS

  19. AutoQuery Data

  20. AutoQuery Memory

  21. AutoQuery Service

  22. AutoQuery DynamoDB

  23. Server Events

    1. Overview
    2. JavaScript Client
    3. C# Server Events Client
    4. Redis Server Events
  24. Service Gateway

    1. Overview
    2. Service Discovery
  25. Encrypted Messaging

    1. Overview
    2. Encrypted Client
  26. Plugins

    1. Auto Query
    2. Server Sent Events
    3. Swagger API
    4. Postman
    5. Request logger
    6. Sitemaps
    7. Cancellable Requests
    8. CorsFeature
  27. Tests

    1. Testing
    2. HowTo write unit/integration tests
  28. ServiceStackVS

    1. Install ServiceStackVS
    2. Add ServiceStack Reference
    3. TypeScript React Template
    4. React, Redux Chat App
    5. AngularJS App Template
    6. React Desktop Apps
  29. Other Languages

    1. FSharp
      1. Add ServiceStack Reference
    2. VB.NET
      1. Add ServiceStack Reference
    3. Swift
    4. Swift Add Reference
    5. Java
      1. Add ServiceStack Reference
      2. Android Studio & IntelliJ
      3. Eclipse
  30. Amazon Web Services

  31. ServiceStack.Aws

  32. PocoDynamo

  33. AWS Live Demos

  34. Getting Started with AWS

  35. Deployment

    1. Deploy Multiple Sites to single AWS Instance
      1. Simple Deployments to AWS with WebDeploy
    2. Advanced Deployments with OctopusDeploy
  36. Install 3rd Party Products

    1. Redis on Windows
    2. RabbitMQ on Windows
  37. Use Cases

    1. Single Page Apps
    2. HTML, CSS and JS Minifiers
    3. Azure
    4. Connecting to Azure Redis via SSL
    5. Logging
    6. Bundling and Minification
    7. NHibernate
  38. Performance

    1. Real world performance
  39. Other Products

    1. ServiceStack.Redis
    2. ServiceStack.OrmLite
    3. ServiceStack.Text
  40. Future

    1. Roadmap
Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.