Cascade delete with Bookshelf.js
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.


This Bookshelf.js plugin provides cascade delete with a simple configuration on your models.


npm version build status coverage status


Install the package via npm:

$ npm install --save bookshelf-cascade-delete


Require and register the bookshelf-cascade-delete plugin:

var bookshelf = require('bookshelf')(knex);
var cascadeDelete = require('bookshelf-cascade-delete');


Define which relations depend on your model when it's destroyed with the dependents prototype property:

var Post = bookshelf.Model.extend({
  tableName: 'Post'

var Author = bookshelf.Model.extend({
  tableName: 'Author',
  posts: function() {
    return this.hasMany(Post);
}, {
  dependents: ['posts']

If you're using the ES6 class syntax, define dependents as static property:

class Author extends bookshelf.Model {
  get tableName() {
    return 'Author';

  posts() {
    return this.hasMany(Post);

  static dependents = ['posts'];

Use destroy to delete your model:

Author.forge({ id: 1 }).destroy();

A transaction is created and all the cascade queries executed:

DELETE FROM "Post" where "author_id" IN (1)
DELETE FROM "Author" where "id" IN (1)

You can pass an existing transaction as you would normally do:

bookshelf.transaction(function(transaction) {
  return Author.forge({ id: 1 }).destroy({ transacting: transaction })
}).then(function() {
  return Author.forge({ id: 2 }).destroy({ transacting: transaction })

It's possible to disable the cascade delete with the cascadeDelete option:

Author.forge({ id: 1 }).destroy({ cascadeDelete: false });

Since this plugin extends the destroy method, if you're extending or overriding it on your models make sure to call its prototype after your work is done:

var Author = bookshelf.Model.extend({
  tableName: 'Author',
  posts: function() {
    return this.hasMany(Post);
  destroy: function() {
    // Do some stuff.

    // Call the destroy prototype method.
    bookshelf.Model.prototype.destroy.apply(this, arguments);
}, {
  dependents: ['posts']


Contributions are welcome and greatly appreciated, so feel free to fork this repository and submit pull requests.

bookshelf-cascade-delete supports PostgreSQL and MySQL. You can find test suites for each of these database engines in the test/postgres and test/mysql folders.

Setting up

  • Fork and clone the bookshelf-cascade-delete repository.
  • Duplicate test/postgres/knexfile.js.dist and test/mysql/knexfile.js.dist files and update them to your needs.
  • Make sure all the tests pass:
$ npm test


bookshelf-cascade-delete enforces linting using ESLint with the Seegno-flavored ESLint config. We recommend you to install an eslint plugin in your editor of choice, although you can run the linter anytime with:

$ eslint src test

Pull Request

Please follow these advices to simplify the pull request workflow:

  • If you add or enhance functionality, an update of usage section should be part of the PR.
  • If your PR fixes a bug you should include tests that at least fail before your code changes and pass after.
  • Keep your branch rebased and fix all conflicts before submitting.
  • Make sure Travis build status is ok.


This plugin's code is heavily inspired on the tkellen contribution for this issue, so cheers to him for making our job really easy!