Restful Web-Services Best Practices

DZone 's Guide to

Restful Web-Services Best Practices

· Integration Zone ·
Free Resource
Some guidelines that I follow while designing the Restful Web-Services (here after referred to as services):

URI Design:

URIs are main part of a web-service interface. It’s painfully hard to change them once services are published and used by internal/external clients. Example URI: /newsletter/{id}/subscription/{sub_id}. URI should
  1. be concise.
  2. be easy to remember.
  3. un-ambiguously identify the target resource.
  4. have only nouns as part of URI. URI should identify the resource not action. HTTP Request Method itself implies action (Get implies search, POST implies create, PUT implies update and Delete implies removal of resource).
  5. Modular. In any non-trivial web-service, number of methods can easily grow to relatively large number (typically many tens) over time. First part of the URI should identify the module (e.g. newsletter, sweepstake, quizpoll, users etc) and all URIs for that module should live under it hierarchically. e.g. invocation of  /newsletter/15 would operate on the newsletter with id 15 and /newsletter/15/subscription/435 would operate on subscription 435 of the newsletter 15.


There will come a time when there will be a new major release of services that may not be backward compatible and we would want to maintain two versions during the period of client upgrade. Versioning should be built into the services from the very beginning as it's hard to introduce once services are published. Client should pass version information in 'Accept' request header (e.g. Accept: application/xml;version=1.0) that server can use. In case version passed is unsupported, server should respond with Http Response Code 415 and an informative message.


Services should be coarse grained. Services will typically map to top level domain objects. In a well designed domain model, operations on top level domain objects will neatly map to business use cases.(Exposing every single persistent object via web-service is not a good practice. It exposes internal application design, adds redundant/un-used services and makes service hard to understand/use) 

Request/Response mime types:

Service should use standard HTTP headers to consume/produce different mime types. That way new content types can be easily supported in future without changing service interface. Content-type headers of the request  determines the type of the content service should expect and accept header of the request should determine the type of response body that services produces.(Typical content-type and accept headers:  application/xml and application/json).


Services should cache only successful GET requests. Caching at multiple layers is needed to have good performance. Persistent layer caching is a must. Additionally method level caching can be added. Services should also include cache-control header in response, so client can decide whether or not it can cache the response. Additionally, for cachable responses, server should set HTTP 'Vary' header to indicate that the response is cacheable based on the URL plus the returned Content-Type:
Vary: Content-Type


Logging should follow one log per request pattern. In a multi user environment, it can be great trouble-shooting help to have one log per request. All logs for the request can be accumulated in request thread and printed once at the end of the request. 

Error Handling:

  1. Service should stick to HTTP Status Codes for communicating success/failure that can be used by program clients. At times it might be necessary to add Custom HTTP Status Codes for very specific use case (these should be an exception and kept to a minimum--to a very few). Any contextual information about the error should be included in reason phrase of HTTP response or custom HTTP response headers.
  2. Service requests involving user entered data (POST, PUT) should additionally include a list of user error messages in the response body that can be used to clearly display to the human users the action needed to correct the error condition. Here I also like to add a new custom HTTP Status code (450) that clearly communicates to the client that it’s user data validation error.


Document should include (for each service method):

  1. HTTP Method
  2. URI
  3. Accept and Content-Type HTTP Request Headers
  4. All possible HTTP Response codes
  5. Any custom Headers
  6. Sample Response
  7. Sample request body  for PUT, POST requests
  8. Schema (xsd files for each request and response)

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}