Sharing Our Passion for Technology
& continuous learning
〈  Back to Blog

Node Reference - Get Product by Id

Teammates sitting together and looking at code


This article builds on the prior article: Node Reference - Listing.

Add Get By Id

At this point, we have only one way to get Products. We have to list all products and page through them to find the one we want. However, a lot of the time, a RESTful service client will have an exact ID of the entity it is interested in.

The REST HTTP verb for reading and entity is HTTP GET. To facilitate retrieving a specific entity or product, it is typical for RESTful services to have a GET endpoint that serves the individual resource using a non-changing, unique identifier. While more formalized architectural styles like HATEOAS exist, it is generally accepted practice to simply place this endpoint directly “under” the listing URL. In other words, whereas our product listing URL is “/products/”, our individual product URL will be “/products/{productId}”. Conversely, if our service wanted to support filtering products on other (possibly non-unique) fields, we would add a optional query parameter to our listing endpoint that would filter the list to only matching items.

This is an excellent opportunity for you, the reader, to take the lead in test driving this feature. If you’d like a primer on test driving, we recommend listening to the first 45 minutes of this Uncle Bob TDD video.

Start by creating a products/getProductById.spec.js file and writing unit tests to drive the behavior we want from this endpoint. Remember to reference the DyanamoDB DocumentClient API to ensure that the call is mocked properly. Also remember to think about and test for corner cases. What happens if a request specifies an id that does not exist? (It should probably return a 404.)

When you are ready, create the products/getProductById.js file and implement the test cases you have written so far.

How many test cases should someone write before implementing them? This is mostly a matter of team preference. However, there are two checks one should keep in mind:

1. Beware of writing too many test cases. This can cause the implementation to grow in complexity too fast without a safe stopping point to refactor.
2. Beware of writing so few (maybe one) test cases that you find that the implementation is "accidentally" providing functionality for which there is not a test yet.

Now that tests have been written and implemented, it is a good time to go back over the code and refactor. Double check that everything is readable. Rename function and variables to make their purpose and functionality clearer. If you find that you wrote some comments to explain why you were doing something, ask yourself if those comments could be replaced by a better function or variable names.

Feel free to checkout our implementation of this functionality.


While caching is outside of the scope of this series of articles, we’d like to briefly touch on the topic of caching and leave it up to you in order to explore further if needed.

All browsers employ HTTP caching. Browsers typically treat GET requests as cacheable. However, since we are writing the client code, instead of using a browser as a client, it is up to us to employ any caching methods to cut down on client-server interactions. ETags are an accurate way to know if an entity has changed or not. Alternatives include using the lastModified property introduced in Node Reference - Put to set the Last-Modified HTTP response header. Then conditional requests containing If-Modified-Since or If-Unmodified-Since headers can make use of this header.

AWS also provides an in-memory caching option call Amazon DynamoDB Accelerator (DAX)) that can be used for read-intensive, latency-sensitive applications. We recommend analyzing the benefits/drawbacks of any caching strategy prior to implementing DAX.

Table of Contents

If you have questions or feedback on this series, contact the authors at

〈  Back to Blog