Node function to walk through file system and make sure it has a matching db record
./content/userstyles/' + style._id + '/style.css


This appears to be a very brittle convention. It assumes the styles live in a specific directory. Not following the convention, it might lead to more unsynced files. You need a more robust way to handle this. For instance, ID'ing the file using its path.

fs.access('./content/userstyles/' + style._id + '/style.css', function(err) {
    if (err &amp;&amp; err.code === 'ENOENT') {
      //Can't find the style file, i need to delete it
      Style.remove({_id: style._id}, function(err, result) {


Instead of a back-to-back filesystem and DB operation, why not operate in batches. Like first get a list of files from DB. Next, check if you can access them all. Only after then do you wipe the DB with missing ones. This way, you have a much more linear set of operations instead of one step doing too many at a time.

It can even be simplified into something like similar to this pseudo-code implementation:

db.getStyles()                                      // Get all styles
  .map(path =&gt; { path, hasAccess: hasAccess(path)}) // Get access
  .filter(file =&gt; !file.hasAccess)                  // Get unaccessible
  .forEach(path =&gt; db.delete(path));                // Delete


Now if I rememer correctly, fs-plus has a method to list down all the possible paths under a given path. I think it was listTreeSync. This way, instead of having a callback run on every file and directory, you can simply analyze the array of paths returned by the function. Equates to lesser filesystem operations.

fsp.listTreeSync(dir)
   .map(path =&gt; extractId(path))
   .forEach(id=&gt; storeOrDeleteId(id));


Also, I recommend writing it in a synchronous manner. Unless you're multiplexing other operations in the same app together with this, you'll see no benefit from writing this in an asynchronous manner if this is the only operation that runs at a given time.