Rails and external services: allow for failure

At Cook Smarts we rely on external services for payments, image processing, and more. Sometimes, the app will fail to reach a service. Perhaps the service is down or there’s a network error somewhere along the line.

How can we tolerate such errors with a minimum impact to the user?

Here’s an example of how we addressed a recurring error with an external service:

A user can export a recipe as a PDF, including an image of the meal.* We retrieve the appropriately-sized image form reSRC, our external image processor.

PDF exported recipe from Cook Smarts

Occasionally, the connection to retrieve the image times out, preventing the image from importing into the PDF. Before, this caused an exception, preventing the user from exporting the recipe at all.

For a better user experience, we now show a friendly error message in place of the image.

Exported PDF recipe from Cook Smarts with image error message

To show the friendly error instead of a fatal exception, we use ‘begin’ and ‘rescue’ in Ruby, in the midst of our Prawn PDF code.

Fault tolerance is crucial when using external services. Assume that your app and the services will clash sometimes, and plan accordingly.

* Eventually, we’ll cache these PDF’s, but for now they are generated whenever a user requests them.