How I built an in-memory explicit content filter in Node.js (200ms latency, zero images saved) A developer built an in-memory explicit content filter for Node.js that classifies images without ever writing them to disk, achieving roughly 200ms latency. The solution uses multer's memoryStorage and the nsfwjs library with TensorFlow.js to keep images only in RAM, addressing privacy and liability concerns. The developer also launched an API called Tabu based on this logic. If you allow user-generated content in your app, you eventually run into a massive liability problem. Users will upload NSFW images. I ran into this exact problem when Apple rejected my previous app under Guideline 1.2 User Generated Content . I needed a filter, but the standard way most tutorials teach you to handle this is flawed. Usually, the process goes like this: The problem? The explicit image actually hits your hard drive before you know it is explicit. If the background job fails or is delayed, you are temporarily hosting illegal or policy-violating content on your servers. To solve this, I built a single Node.js endpoint that runs the entire classification in memory. Instead of saving the file to disk, the server receives the image as a buffer, passes that buffer directly to a lightweight machine learning model, gets the score, and immediately destroys the buffer. The image never touches a hard drive. Here is the core logic using the open-source nsfwjs library and TensorFlow.js: js const express = require 'express' ; const multer = require 'multer' ; const tf = require '@tensorflow/tfjs-node' ; const nsfwjs = require 'nsfwjs' ; const app = express ; // Keep the file in memory, do not write to disk const upload = multer { storage: multer.memoryStorage } ; let model; const loadModel = async = { model = await nsfwjs.load ; }; app.post '/moderate', upload.single 'image' , async req, res = { if req.file { return res.status 400 .json { error: 'No image provided' } ; } try { // 1. Decode the image buffer directly from memory const imageTensor = tf.node.decodeImage req.file.buffer, 3 ; // 2. Pass the tensor to the model const predictions = await model.classify imageTensor ; // 3. Destroy the tensor to free memory immediately imageTensor.dispose ; // 4. Return the scores return res.json predictions ; } catch error { return res.status 500 .json { error: 'Processing failed' } ; } } ; loadModel .then = app.listen 3000 ; 1. Total Privacy. Because we use multer.memoryStorage , the image exists only in RAM for the fraction of a second it takes to run the classification. Once the request ends, Node.js garbage collects the buffer. You can legally guarantee your users that you are not storing their private photos. 2. Speed. Bypassing the file system completely keeps the classification extremely fast. In my testing, it drops to roughly 200ms per image on a standard VPS. 3. Simplicity. It is a synchronous API call. You can run this check before your database transaction even commits, keeping your backend architecture clean. If you want to run this yourself, the code snippet above is pretty much all you need to get started. Just watch your server memory, as TensorFlow tensors will cause a memory leak if you forget to call .dispose . If you don't want to bother hosting the ML models or managing the RAM yourself, I actually wrapped this exact logic into an API called Tabu https://tabushield.com that I launched recently. It has a free tier that is plenty for testing, so feel free to use it if you want to skip the server setup. Let me know how you guys handle image moderation in your own side projects