Hah, true enough. But the other half of what makes Spray work is the high-level abstraction possible, which makes it easy to handle these different things generically. Consider e.g. https://github.com/4lex1v/Sprayed/blob/master/src/main/scala... , which is an example of abstracting a possible "context" for a value, with implementations for futures or possible errors (both things that go has direct support for, but it's much less clumsy to work with these things when they're just ordinary objects that follow the ordinary rules of the language). You can abstract over those contexts, writing one method that can handle a list of async calls or a list of possibly-failing calls. You can extend it with your own data types, e.g. you can do session-in-view in a principled way, using ordinary language features rather than magic annotations, by having a context that represents "database operation".