Limitations of Sequelize

Jordan Ell
Riipen Engineering
Published in
5 min readMar 22, 2019

With the release of Sequelize 5, now seems like a good time to write about the limitations of Sequelize (to date) which I have, and you are more than likely to, come across while working with this popular ORM.

Polymorphism.

Associations.

Sequelize does not support polymorphism in a direct manor, however, they do technically support it through the use of association scopes. Essentially it’s a “roll your own” polymorphism type of mechanism.

An example would be a comment that can belong to a post or a photo . In Sequelize, this could be written as such.

Notice the use of the getItem function which will return the associated object which the comment is related to polymorpically. This is where the lack of true polymorphism in Sequelize shows up. So overall, not a terrible workaround.

It should be noted as well that if set up as shown above, associations such as the comment belonging to a post can be used in eager loading mechanism in sequelize as you would expect. However, you must know the polymorphic association type ahead of your query, or you must eager load every associated type.

Obviously if you have a large list of possible associations, this method can get out of hand quite quickly. You will need to implement some sort of list function which can obtain all possible polymorphic associations and insert them into your query in order to keep your code DRY. And again, you will need to do the same once handling the response of the query since all associations will be split into their proper model name (ie. comments[0].Post and comments[0].Photo with onlyone of those associations actually having any value depending on the polymorphic type).

Composite Foreign Keys.

The very first issue I ran into with Sequelize once seriously using it was its lack of support for composite foreign keys. This issue is largely tied in with the lack of native polymorphic support as mentioned earlier and may cause you some headaches.

Luckily you can mostly get around this issue by using scopes in the association.

Counter Cache.

Counter caches are exactly what they sound like, they store a counter, usually, for how many of a given relationship a particular object has. An example would be an author has a certain number of books.

Sequelize has no native support for this whatsoever (although they use to but took it out claiming it could all be done with hooks), and if you are building a web or mobile application you will likely come across this need. Here is an article breaking down exactly how to create re-usable infrastructure for counter caches with Sequelize https://medium.com/riipen-engineering/sequelize-counter-cache-patch-146e5e29abf2.

Cascading Deletes.

Paranoid.

Yes, Sequelize does support cascading deletes, it would be crazy for an ORM not to. Where it fell short for a particular use case was combining the paranoid option with cascading deletes. What if I want to soft delete my book model, and at the same time soft delete all of it’s tags . Sequelize will not cascade this soft delete down from the book to all of its tags or any other associated models.

Here is a quick code sample for how to roll your own paranoid cascading deletes.

Bulk Cascades.

You will notice on paranoid-delete-cascade.js:46 I mention that Sequelize also does not support cascade deleting when performing bulk deletes. This is another caveat to keep in mind when navigating the cascading delete landscape in Sequelize.

Eager Loading Pagination.

In an effort to reduce the number of times you are hitting the database, you may want to eager load associations. An extremely common use case here is that you want to load “X of the most recent associations” for a given model. For instance, give me a list of authorsand their 5 most recent books. I would think to write something like this in Sequelize.

models.Author.findAll({
include: [
{ model: models.Book, limit: 5 },
],
limit: 10,
});

However, this will not work. It will load all books for the 10 authors, even if an author has thousands of books. While not the end of the world, this maybe an an issue for you.

Unfortunately there is no snippet of code I can give you to fix this workaround. You will need to write some custom wrapper which takes the result of this query and then filters the number of loaded books down to the intended 5.

Single Table Inheritance.

Single table inheritance is a common pattern in web applications where you have multiple data models which represent different “types” of a common model. For example, you may have a marketplace which sells products and those specific products are pens and pencils . Ideally you could have a single “products” table which has all the common attributes such as price color etc and also has the pen and pencil specific columns like ink-type or lead-type and then to distiguish between a pen record or a pencil record, you simply add a type column which can be either “pen” or “pencil”.

This is an extremely common practice, however, Sequelize has no support for this functionality and there is no easy workaround that will not cause you a bunch of headaches. The same can also be said of multi table inheritance, which is less commonly used, but still can be valid in a few cases.

Other.

Aside from the major points outlined above, here is a list of smaller cases where Sequelize might give you more trouble than you would expect.

  1. Caching — there is no native built in caching mechanism for Sequelize. The only solution I was able to find was this redis based package. Good luck with cache invalidation.
  2. Documentation — I have found myself several times needing to read the Sequelize source code in order to fully understand how something works.
  3. Text based search queries — see this article for details.
  4. Query builder — no query builder currently exists.

There are other limitations to Sequelize not listed here, but most of them are obscure enough that you are very unlikely to come across them in a normal web / mobile based application.

Happy ORM’ing!

--

--