Article: REST Anti-Patterns

| by Mark Little Follow 15 Followers on Jul 01, 2008. Estimated reading time: 1 minute |
So you've decided to develop your application on the Web. The next step is probably WS-* or REST. This time you're convinced that REST is the way to go: how hard can it be compared to the other approaches? Well as Stefan discusses in this article, using HTTP doesn't necessarily mean you're being very RESTful.
HTTP is nothing new, but it has been applied in a wide variety of ways. Some of them were in line with the ideas the Web’s designers had in mind, but many were not. Applying REST principles to your HTTP applications, whether you build them for human consumption, for use by another program, or both, means that you do the exact opposite: You try to use the Web “correctly”, or if you object to the idea that one is “right” and one is “wrong”: in a RESTful way. For many, this is indeed a very new approach.
In his article he goes into detail on 8 common anti-patterns that he has encountered (and at least once been responsible for):

  • Tunneling everything through GET
  • Tunneling everything through POST
  • Ignoring caching
  • Ignoring response codes
  • Misusing cookies
  • Forgetting hypermedia
  • Ignoring MIME types
  • Breaking self-descripteness
As with any architectural style, whether it is for software, hardware or buildings, it's important to know the do's and don'ts, especially if they come from first-hand experience, so you can avoid making the same mistakes as others: you should be looking to make all new mistakes and learning from them.

Rate this Article

Adoption Stage

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Great Points; Here's Another... by Ray Krueger

I think this probably ties into your "Tunneling through GET" point. I've seen a few applications with interfaces like this...{url encoded xml goes here}
and{url encoded json goes here}

It seems akin to "Tunneling Messaging Through GET"...

Great stuff, be good to read more by Colin Jack

Really good stuff, I've been reading a lot about REST recently and this is exactly the sort of content that is needed for people like me who are only now looking into the topic in detail.

In fact its so good that I think it would be useful if (at some point) there were further articles that could go into detail on some of the aspects you cover, in particular "Breaking self-descriptiveness" and "Forgetting hypermedia". Personally I found that initially these aspects of REST were initially difficult to grasp.

I was also wondering whether you were aware of an existing REST reference application, particular one that covers an enterprise application?

Re: Great stuff, be good to read more by Stefan Tilkov

Thanks Colin. The only attempt at an enterprise application reference implementation is Joe Gregorio's REST DayTrader variant. Any suggestion what other enterprise app could be used as an example would be greatly appreciated.

Can you expand a bit? by Karl Krukow

Hello Stefan,

Thanks for another great article — I am looking forward to the future ones that will go more in depth.

I was wondering about two of your points:

Point 5. “misusing cookies” - As you mention, the usual way of performing authentication in web applications is to assign a session id to each fresh request, keep this as a cookie and then store session information at the server which says, e.g., the session id is authenticated and corresponds to user X. You seem to argue that the restful approach would be to avoid this and use e.g. HTTP Basic or Digest authentication, is this correct? At first thought this seems impractical… What would you say? In practice what would you do for your ‘common-case ajax web-app’?

Point 6. Hypermedia. I like this principle, but I’m wondering about the consequences of taking this approach to the extreme. Often you want composite or ‘aggregate’ representation of resources. For example, a user might have a userprofile and account information, etc. If you want a representation of this user, say in a web-app, you often want a page composing username (a property of the user resource) with adress (say userprofile) and account number (account resource information). You can fetch the user resource which links to it’s user profile which may in turn link to the account. In this approach, being REST compliant entails many more HTTP request than a single aggregate i.e., non-hypermedia based approach.

In general suppose you want a summary view of a collection resource. You can represent your collection as a list of links to the individual resources, or you can aggregate the collection to one large response. If you do the former, you potentially have n requests where a single would be enough. It reminds me of the n+1 problem for databases...

Of course you may argue the other way around, but the discussion is still valid.

What is your opinion on this? It it better to create a new aggregate resource specifically for this purpose?


Re: Can you expand a bit? by Stefan Tilkov

Thanks Karl. Adressing your first point: Wherever possible, I would indeed suggest using HTTP authentication instead of cookies. But even if you use cookies, it's perfectly fine to do so if you avoid session state. The way to do this is to encode a token, in the cookie that the server can validate without session state. Aristotle Pagaltzis recently summarized how to do this in a discussion in the Yahoo! rest-discuss group:

Regarding your second point: if I understand you correctly, you want to use aggregate resources. This is fine, and I don't see a conflict with hypermedia. On the contrary, you can actually include links to the details view and back, offering your users to navigate into the direction that's more appropriate for them.

auth_token = concat( username, ":", expiration_datetime );
msghash = digest_hmac( concat( server_secret, ":", auth_token ) );
cookie = concat( msghash, ":", auth_token );

Rails 2.1 uses a similar approach, but encodes "session" state (which is really client state) in the cookie – a practice I don't really like that much, but would claim is RESTful nonetheless.

tunneling through POST by Bryan Taylor

Regarding tunneling through POST, you wrote "It actually doesn’t end up violating any REST principles so much – it simply ignores them."

This is interesting, and it echos a point I've made: if I do SOAP and I as the service designer I'm not able or willing to declare any of my operations permanently "safe", then the HTTP spec tells me I SHOULD use POST, and I'm not certainly not violating any principle of REST. I'd certainly agree it's not in the "spirit" of REST, which wants me to introduce safe resources for most of my "nouns", but does SOAP violate any objective principle of REST? I think it's just not idiomatic, but at this point it's not an objective, technical criteria but a subjective, artistic one. When discussing the GoF patterns, I don't think there's much artistic interpretation that goes on to know if I have a factory pattern, strategy pattern, command pattern, or whatever. Does REST boil down to "I know it when I see it".

If I look at SOAP as a way to send a message to a method of a some kind of virtual object ("Simple Object Access Protocol", after all), the fact that object behavior is encapsulated means that I, as the web service builder and a client of underlying class, don't know if the method is safe or not because it doesn't tell me that it is. It could be getPurchaseOrder(), but I really don't know if this is an idempotent operation. Often it is, but I can't guarantee that it is without some kind of language semantics like some kind of @Safe annotation (which doesn't exist to my knowledge). Absent something like this, isn't POST the only reasonable thing to use? Even if I know the base implementation class uses a safe implementation, a runtime instance could polymorph this safe behavior into something that's not safe, right?

Anyway, it seems that the real idiomatic difference is between REST and OO, not just REST and SOAP. I'd like to understand what it is about the web that makes REST a "nicer" programming paradigm than OO. Conversely, why not apply REST everywhere, like say in the programming language itself. Imagine that Object declares get(), put(), post(), and delete() and is final. Imagine a uri scheme object:// instead of references. Would anybody use this language? It'd certainly simplify my javadocs :)

The real challenge is letting go of services/methods by Jakub Nešetřil

Congratulations Stefan to a nice article. A lot of the patterns are really notorious - however, the one I find most frequented seems to be missing.

In my opinion, the real challenge is getting rid of the method-oriented afterthoughts of SOAP and RMI. In a certain way, RMI is compatible with anybody's programming style, just putting a network between the method invocations.

With REST where action is a result of state changes, you have to convince your colleagues to a mental paradigm shift to state-automatons or data-flow programming. That's the part I find really hard.

Re: tunneling through POST by Paul Beckford

Anyway, it seems that the real idiomatic difference is between REST and OO, not just REST and SOAP.

I use to think this, but it is another misconception. REST and true (late-bound) OO are very similar in fact. Think of the REST uniform connector idea as an object with a fixed protocol (fixed number of methods), and resources as parameters to those methods.

Using a "uniform connector" means that the client needs to know very little about the server (other than the server understands the uniform protocol). You can use the same technique with Objects if you wished (no need for final though), with the same effect of reduced coupling between the client and the server.

REST is a response to the problem of large scale application distribution. If I control both client and server in the same memory space then the constraint of a fixed uniform connector is no longer as appealing :)


Question on "Ignoring status codes" by mani doraisamy

Thanks for another great article, Stefan.
Quick question on Ignoring status codes:
"For example, a 201 (“Created”) response code signals that a new resource has been created, the URI of which can be found in a Location header in the response."
Does this mean there has to be 2 requests: one to create and the other to read the content from the URI? Is this a feasible option for human consumption?

Re: Question on by Alexander Klimetschek

Does this mean there has to be 2 requests: one to create and the other to read the content from the URI? Is this a feasible option for human consumption?

201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.

Re: Question on "Ignoring status codes" by Craig McClanahan

Does this mean there has to be 2 requests

Expanding a bit on Alexander's response, this does not mean two requests. On the response to the "create" request, you return both the 201 "Created" status code, and an HTTP "Location:" header, whose value should be an absolute URL to the newly created resource.

Exposing Algorithms by Eric Larson

One pattern I've seem people follow is using query string parameters when the resource is exposing some sort of algorithm or dynamic representation. The thing to watch out for is that you do not define this pattern in terms of the algorithm or code producing the page, but rather the meaning to the user. For example, adding a "page=3" argument to something like a feed makes sense because you are asking for a slightly different representation of the resource. But, if you have a set of parameters describing the feed such as "tag=java" and "year=2008" then there is a good chance you are exposing an algorithm that would be better served as a simple resource.

Re: tunneling through POST by Erik Johnson

The extreme case of tunneling via POST through a single URI certainly has limited appeal. For one thing, it precludes the use of hypermedia links in content (they would all point to same URL).

That said, I don't see tunneling through POST as an automatic anti-pattern. For one thing, given the presence of an otherwise complete URI-space (with the requisite GET/PUT/etc. support), POST provides a way to multiplex operations. It isn't feasible to identify each potentially unique content-set and there are times when one round-trip is preferred :).

I just don't want to see POST==BAD become a conclusion without more thought put into it.

Re: Question on "Ignoring status codes" by mani doraisamy

Not sure if i explained the question correctly. I am talking about a usecase where the user hits a create button (for a new PurchaseOrder) and expects the browser to show up the created resource (i.e. PurchaseOrder). How would this usecase translate into REST calls?

Re: Question on "Ignoring status codes" by Stefan Tilkov

Unfortunately, browsers don't follow the "Location" header sent back with a 201 (I don't really have any idea why). To avoid re-submitting, common practice is to send a redirect to the new resource after POST, which will make the browser issue a GET to it.

Re: Question on "Ignoring status codes" by mani doraisamy

I assume that redirection means 2 requests from browser:

1) create (or any action) request - as POST

2) redirection request to get the resource - as GET.

While most of the MVC frameworks will return the view after the action in a single request. Is this the cost we have to pay for a cleaner architecture? Or is there a better way?

Re: tunneling through POST by Bryan Taylor

When you say "tunneling via POST through a single URI certainly has limited appeal", I ask appeal to who? Certainly there are a lot of enterprises deploying SOAP on a large scale that do exactly that. If you had said it's not idiomatic for REST, then certainly you'd be right.

I just wonder whether or not embedded URIs and the concept of "hypermedia as the engine of application state" is really a human usability thing. If the consumer is code, I don't see any particular benefit. If you have account_id="123" embedded vs an actual account URI the client can actually use this in a more flexible way, where it and not the server decides where it wants to go next. Doesn't HATEOAS actually increase the burden on the server to completely define the workflows that use it's resources as state transitions it supports via links? I'm not saying that is good or bad, just that it is a constraint that many systems, especially in enterprise settings will not be capable of conforming to. I have no doubt that when you can meet that constraint, I do see many benefits that will flow from it.

Re: tunneling through POST by Paul Beckford

Hi Bryan,

Maybe I was too subtle in my last response, but REST actively avoids RPC (SOAP) since it encodes application specific behaviour (operations) in the connector interface itself. This means that each time the behaviour of your server changes so does the interface and hence all clients must change too. This approach is brittle causing you to recompile your client with new a new stub. With a uniform connector and a self describing resource with hyperlinks, then you can represent application state as additional resources which are accessible through links. You can add or delete links as you like exposing and hiding state without braking the uniform connector interface.

In Roy Fieldings dissertation he goes through a number of client server architectural styles and lists the pros and cons for each. If high dependency between client and server is not a problem then an alternative to REST (like RPC) may be your best bet. The success of the web is that it avoids such coupling which means that it can evolve and change without ever needing to recompile the client (browser). This is where REST excels.

Re: Question on by Stefan Tilkov

I assume that redirection means 2 requests from browser:
1) create (or any action) request - as POST
2) redirection request to get the resource - as GET.

There is no reason at all a framework would have to do all actions via POST, so in many cases, a single request is fine. When a POST is used, there should be a redirect simply to avoid the warning when a user hits "refresh", and to support bookmarking. Things would be much better if browsers supported PUT and DELETE and followed Location headers in 201 responses - but sadly, they don't.

great stuff! by James Strachan

Awesome article Stefan - you've definitely nailed most of the anti-patterns folks tend to hit in my experience. REST is definitely one of those things some folks think they are being RESTful because they use some GET and maybe some POST - articles like this really help to clarify things.

The only other grey areas of REST I've seen that are not mentioned (but are kinda tiny nits really) are...

* no easy way to associate XSDs with MIME types for XML representations - there seems to be a few different ways folks try this hacking the MIME type for example. We could maybe do with some kinda standardised way to associate metadata more easily; maybe the AtomPub service document idea or something WADLish. Though given JSON tends to be easier than XML - maybe this isn't such a biggie :)

* using URIs instead of accept content-type headers to influence the representation. Most good frameworks tend to have a convention where you can, say, append ".xml" or ".json" or ".yaml" or whatever to force the representation without having to specify accept headers. While a bit of a hack it is kinda handy allowing folks to use any browser to view different representations - without relying on custom plugins in browsers etc. It might be nice to kinda standardise this kinda stuff.

But those are tiny nits - these 10 anti-patterns are right on the money! Keep it up! :)

We seem to have similar timing ;) by Benjamin Carlyle

I was mulling over the phrase "REST Patterns" as it was coming up as a training need in my office. I'm focusing on patterns for machine-to-machine communication, but have started to collect a few myself: REST Patterns @

I have quite a bit more work to do, and I still have to clear up some cloudy IP issues before I am able to get out my complete list :-/

Re: tunneling through POST by Bryan Taylor

SOAP uses a rich (non-uniform) interface, because that's what you do when you program with objects, and SOAP tries to mimick this. So you're argument for the uniform interface is really one against object oriented programming generally, as you haven't told me any web specific reason to necessitate the switch of architectural style. Somehow I don't think object oriented coding would be as popular and successful if it was as brittle as you say something without the uniform interface must be.

I also have to question the idea that RESTful resources are normally "self describing". In fact, this is a key weakness of REST that presently prevents widespread adoption of in enterprise settings (at least until WADL or WSDL 2.0 gain more traction there). The idea that you won't have to redeploy a new client if the server behavior changes in REST is a bit far fetched for the same reason. The fact that hypermedia has embedded URIs doesn't mean that client code knows how to translate these URI into a semantic meaning, nor does it protect the client from having to be changed if new state transitions are added or others are taken away. Application code must understand the interchange format in detail. REST gives you no way to say anything more descriptive than the media-type such as "application/xml". When I do a GET, I may discover that I don't understand the payload or that it's changed from what my client code supports. The wonderful state machine via links is then useless to me. Without service descriptions, such changes happen without warning at runtime and break things, even if I got to the /account/1234 doc by following HATEOUS navigations. Moreover, if I'm a client constructing a POST or a PUT, I don't even have the benefit of an example. I have no way to know what the payload I should construct must look like, other than XML.

Re: tunneling through POST by Benjamin Carlyle


It is probably best to avoid emotive words like "rich" when comparing REST to the classical O-O style. A fairer comparison might be "unconstrained" (OO) vs uniform (REST).

REST and O-O are closely related. They are both typically client/server request/response messaging paradigms. The client has a reference to the server, and sends it a message. REST is a constrained form of O-O for systems with appreciable network latency, bandwidth constraints, a number of different owners and different release cycles for different components of the architecture.

Perhaps the clearest contrast is between REST and a strongly-typed O-O language. In nice, crinkly java I get a compile error whenever two components disagree on the definition of an interface. The client tries to call method foo. There is no method foo. Bail. In this setting it makes sense to leverage the strongly-typed nature of the language to make sure you don't release junk. You define interfaces in a detailed and domain-specific way that is checked to yield a consistent releasable whole.

In REST, I want the client or the server I deployed literally 10 years ago to work with whatever I am putting out today. I also want whatever I'm putting out today to work with every bit of code written since that time, and every bit of code that will be written in the next 10 years. Getting more specific than necessary is a sub-optimal approach in this environment. There is no compiler to lean on to ensure consistency, and there is no way you could "fix" the old deployed code to work with your latest and greatest. Instead, we lean less on checking and more on uniformity. You don't want to call out thirty or forty versions of an interface that you adapted as your needs changed, and provide explicit support for each. You want something generic, stable and slightly sloppy.

It's not a matter of REST rejecting O-O, or for that matter replacing O-O. It's a matter of different contexts. The growing importance of REST is a recognition that the important bit of software architecture is moving away from "how do I get a release of my project out" to "how do I get my system to work with the other 15 business systems either deployed or in the process of being deployed? How do I future-proof this system in face of constant change?"

To answer your points: Yes, we need better descriptions of what specific URLs are going to do with our PUT and GET requests. Whether that is a matter of producing more machine-readable content or simply more human-readable content is still up for grabs. Yes, we need better document types... the kinds of document types you only come up with by solving real problems. No, I don't think the REST community is at the tipping point where they are solving these problems well enough. I'm hoping they'll/we'll be there soon. At least we know that document-oriented SOA is in the same boat with some of our problems.

See also my GET pattern description. I welcome feedback on this and other pattern descriptions.


Re: PUT, POST, and URIs for creating new resources by Markus Krüger

201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.

If you're using PUT, you should use the specific URL the resource should be stored under, not some generic URL. If you want to create a new resource without specifying the resource URL, the API should use POST instead of PUT.

From RFC 2616, chapter 9.6:

The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY
then make its own decision regarding whether or not to redirect the

Re: Question on "Ignoring status codes" by Sebastian Kirsch

I assume that redirection means 2 requests from browser:

1) create (or any action) request - as POST

2) redirection request to get the resource - as GET.

While most of the MVC frameworks will return the view after the action in a single request. Is this the cost we have to pay for a cleaner architecture? Or is there a better way?

I always assumed that if a PUT is processed successfully, the server should respond with

1) a 201 SC

2) the representation of the created resource as it would be returned by serving a GET request

Referring to Markus' comment, I'd agree that a PUT affects the addressed resource and thus there should be no need for a location header - though it makes great sense when using POST to create resources.

Another thing I'd expect to find in a PUT response is caching information: expires header, etag and - here I contradict myself - maybe even the location header, as I wouldn't rely on a proxy/gateway to cache things if that header isn't present.

Why? The proxy/gateway should then be able to serve a plain GET request for that resource without forwarding the request to the server even once.

"ephimeral" resources by martin sarsale

First of all, great article. Your checklist works pretty good against my API implementation, but I was missing Hyperlinking, which makes a lot of sense.

This is a more open question, which maybe fits better in a forum. Anyway, here it goes:

I'm kind of puzzled on how to expose "ephimeral" resources, for example, the output of a search. I understand the search results are 'a resource' but I'm wondering if there's any rule to create URLs for those.

for example,

and, what happens with paginated searches. Do you like this:

I would love to use "Content-range" but I think it's forcing things a little bit :)

Anyway, really enjoyed the article.

Re: Great stuff, be good to read more by Colin Jack

Thanks for the link, really good content. I'll try to think of a good example but this one gave me a lot of good information.

Re: Question on "Ignoring status codes" by Matthias Wanything

I always assumed that if a PUT is processed successfully, the server should respond with
1) a 201 SC
2) the representation of the created resource as it would be returned by serving a GET request

Not necessarily. REST also allows PUT for updating complete existing resources. Therefore, a 200 SC (or, more common, a 204 No Content) may be more appropriate, depending on the existence of the targeted resource.

Re: Great stuff, be good to read more by Colin Jack

Stefan, I think the travel agency service from CH10 in "RESTful Web Services" would be a good example.

I actually think the authors missed a trick not exploring the travel agency application in more detail. Not to say social bookmarking examples aren't interesting but really I think most examples of services that "have a different grain than the rest of the Web" would be useful.

Another Example for a "REST API" that isn't really RESTful? by Eike Herzbach

Here it says:
The service is designed around the principles of REST, with the goals of simplicity and transparency.

When looking into the documentation, you find stuff like
Custom POST methods:

What are your thoughts about this?

Re: Another Example for a by Stefan Tilkov

Without having taken a closer look, this seems to show either a misunderstanding of REST or unwillingness to label things correctly :-) It seems like a classical example of POST tunneling.

Re: Question on by Alex Popescu

201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.

I might be wrong about it, but I was having the impression that PUT requests are (required to) providing the new/updated resource identifier and what you are explaining applies in fact to POST.


Re: Question on by Alex Popescu

It looks like Markus is agreeing with my point in the next comment :-).


Re: Can you expand a bit? by Valko Yotov

Hi Stefan,

great article, but about the authentication, if you store anything like server_secret on the server like Aristotle Pagaltzis suggests:

"Aside from the server secret, which is easily kept in memory,
you do not need any information external to the cookie in order
to verify it: no on-disk session."

what will happen with scallability? Storing in server memory is even worst from storing on-disk for that purposes. You will have in fact server memory session then?

Re: Can you expand a bit? by Stefan Tilkov

Hi Valko, I'm not sure whether this is a misunderstanding: the server secret is just a single value, such as a string, that exists once per server or server cluster. It's easily kept in configuration, or grabbed from a common service resource during server startup.

Re: Question on by Mike Pearce

If you're creating the resource in the first place with either a PUT or a POST, why would you then need to GET the resource afterwards? Surely you'd have the data available to you?

But, yes, you'd need to do two HTTP requests; the second would be a GET to a URI that was provided as a link in the body of the PUT response. But this will have a useful byproduct if you've got caching enabled as subsequent calls to the resource URI would be cached.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

36 Discuss