Scientyfic World

Real Time Image Moderation Using n8n and AWS Rekognition

Unmoderated user uploads can expose platforms to legal risk, brand damage, and user discomfort. Building an automated, real-time image moderation pipeline helps you intercept inappropriate content before it reaches end...

Share:

Get an AI summary of this article

Real Time Image Moderation Using n8n and AWS Rekognition blog banner image

Unmoderated user uploads can expose platforms to legal risk, brand damage, and user discomfort. Building an automated, real-time image moderation pipeline helps you intercept inappropriate content before it reaches end users. In this post, you’ll learn how to integrate n8n—an open source workflow automation tool—with AWS Rekognition’s moderation API. By the end, you’ll have a fully automated workflow that ingests images, analyzes them for safety, and routes flagged content for human review or approval.

We’ll start by outlining the challenge space: user-generated content (UGC) grows by millions of photos per day on social networks, marketplaces, and forums. Manual moderation can’t scale. AI-powered detection solves this, but you need an elastic, serverless, and low-code integration. n8n provides flexible connectors for AWS services, letting you orchestrate Cloud resources without long code sprints. AWS Rekognition’s DetectModerationLabels API flags explicit content—such as nudity, gore, or suggestive imagery—with confidence scores.

In this guide, you’ll:

  • Configure an S3 bucket to capture uploads and emit events via SNS.
  • Set up AWS IAM roles and n8n credentials for secure API access.
  • Build an n8n workflow: SNS Trigger → S3 Get Object → Rekognition → conditional routing.
  • Implement notifications: email, Slack, or custom dashboards for manual review.
  • Test edge cases and tune confidence thresholds.
  • Discuss performance, error handling, and enterprise-grade scaling.

We assume familiarity with basic AWS services, n8n workflows, and JavaScript. If you need n8n deployment steps, see our previous tutorials: How to Setup n8n on Google Cloud and Deploy n8n on Google Cloud Using Kubernetes. Let’s dive in.

Prerequisites

Before building the moderation pipeline, ensure each component is installed, configured, and verified. We cover AWS account setup, IAM roles, n8n credentials, and local tooling.

1. AWS Account and CLI

  • Create or use an existing AWS account. Verify billing limits, IAM restrictions, and region availability (we’ll use us-east-1).
  • Install AWS CLI (v2). On macOS:
$ brew install awscli
$ aws --version
aws-cli/2.x.x Python/3.x.x Darwin/20.x.x botocore/2.x.x
  • Configure your default profile:
$ aws configure
AWS Access Key ID [None]: YOUR_ACCESS_KEY
AWS Secret Access Key [None]: YOUR_SECRET_KEY
Default region name [None]: us-east-1
Default output format [None]: json

2. IAM Roles and Permissions

Create a role for n8n to call Rekognition, S3, and SNS. Use least-privilege policies:

aws iam create-role \
  --role-name n8nImageModeratorRole \
  --assume-role-policy-document file://trust-policy.json

# trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "lambda.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}

Attach policies:

aws iam attach-role-policy \
  --role-name n8nImageModeratorRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess

aws iam attach-role-policy \
  --role-name n8nImageModeratorRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

aws iam attach-role-policy \
  --role-name n8nImageModeratorRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonSNSFullAccess

3. S3 Bucket for Uploads

Create a dedicated bucket for incoming images. Enforce encryption, versioning, and event notifications:

aws s3api create-bucket \
  --bucket my-app-image-uploads \
  --region us-east-1

aws s3api put-bucket-encryption \
  --bucket my-app-image-uploads \
  --server-side-encryption-configuration '{
    "Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]
  }'

aws s3api put-bucket-versioning \
  --bucket my-app-image-uploads \
  --versioning-configuration Status=Enabled

4. SNS Topic and Subscription

Configure S3 event notifications to publish to an SNS topic whenever a new object is created:

# Create SNS topic
aws sns create-topic --name image-upload-events

# Subscribe n8n endpoint (later) or an email for manual testing
aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:123456789012:image-upload-events \
  --protocol email \
  --notification-endpoint [email protected]

# Link S3 to SNS
aws s3api put-bucket-notification-configuration \
  --bucket my-app-image-uploads \
  --notification-configuration '{
    "TopicConfigurations": [{
      "TopicArn": "arn:aws:sns:us-east-1:123456789012:image-upload-events",
      "Events": ["s3:ObjectCreated:*"]
    }]
  }'

5. n8n Installation and Credentials

Deploy n8n according to one of our guides:

Once n8n is running, add AWS credentials (via Credentials → Amazon Web Services). Use the IAM role’s access key and secret or assume-role configuration. Ensure credentials have access to Rekognition, S3, and SNS.

6. Local Tooling

  • Node.js v14+ (for custom scripts).
  • Postman or cURL (for webhook tests).
  • Slack workspace or email SMTP for notifications.

With these in place, you’re ready to build the end-to-end moderation workflow.

Step-by-Step Implementation

We’ll construct an n8n workflow with these stages:

  1. SNS Trigger: Catch S3 event notifications.
  2. S3 Get Object: Download the image binary.
  3. Rekognition: Detect moderation labels.
  4. Conditional Routing: Safe vs. flagged paths.
  5. Notification or Approval: Email/Slack or store for review.

1. SNS Trigger Node

In n8n, add an AWS SNS Trigger node. Configure:

  • Credentials: Select your AWS credentials.
  • Region: us-east-1.
  • Topic ARN: arn:aws:sns:us-east-1:123456789012:image-upload-events.

This node listens continuously for incoming SNS messages published by S3. The output JSON will include Records[0].Sns.Message which contains the S3 bucket name and object key.

{
  "Records": [
    {
      "Sns": {
        "Message": "{\"Records\":[{\"s3\":{\"bucket\":{\"name\":\"my-app-image-uploads\"},\"object\":{\"key\":\"user123/photo.png\"}}}]}"
      }
    }
  ]
}

2. Extracting Bucket and Key

Add a Function node next. Parse the SNS payload to get bucket and key:

// Function node code
const msg = JSON.parse(items[0].json.Records[0].Sns.Message);
const record = msg.Records[0].s3;
return [{
  json: {
    bucket: record.bucket.name,
    key: decodeURIComponent(record.object.key.replace(/\+/g, ' '))
  }
}];

Why decode? S3 URL-encodes special characters. This ensures accurate object retrieval.

3. S3 Get Object Node

Next, pull the image bytes from S3. Use the AWS S3 node:

  • Operation: Get Object
  • Bucket Name: {{ $json.bucket }}
  • Key: {{ $json.key }}
  • Binary Property: data

This node returns binary data under binary.data. It also includes metadata like content-type and size.

// Sample output structure
{
  "binary": {
    "data": {
      "data": "",
      "mimeType": "image/png",
      "fileName": "photo.png"
    }
  }
}

4. AWS Rekognition: Detect Moderation Labels

Insert an AWS Rekognition node. Configure:

  • Operation: Detect Moderation Labels
  • Image Parameter Type: Binary
  • Binary Property: data
  • Min Confidence: 70 (adjustable threshold)

Under the hood, this invokes DetectModerationLabels API and returns an array of labels:

{
  "ModerationLabels": [
    { "Name": "Explicit Nudity", "Confidence": 85.6 },
    { "Name": "Graphic Male Nudity", "Confidence": 72.3 }
  ]
}

5. Conditional Branching

Use an IF node to split on whether ModerationLabels.length > 0:


First Condition:
{{ $json.ModerationLabels && $json.ModerationLabels.length > 0 }}

True path: flagged content.
False path: safe content.

6a. Flagged Content Workflow

For flagged items, we’ll notify moderators and save metadata for review:

  1. Set node: prepare a review record with bucket, key, labels, and confidence scores.
  2. DynamoDB node (optional): store review jobs with TTL for audit.
  3. Slack node: send a message to #moderation channel.
  4. Email node: drop an alert to the moderation team.
// Example Set node JSON
{
  "bucket": "{{ $json.bucket }}",
  "key": "{{ $json.key }}",
  "labels": "{{ JSON.stringify($json.ModerationLabels) }}"
}

// Slack node config (simplified)
{
  "resource": "chat.postMessage",
  "body": {
    "channel": "#moderation",
    "text": "🚨 Flagged image: s3://{{ $json.bucket }}/{{ $json.key }}\nLabels: {{ $json.ModerationLabels.map(l => l.Name).join(', ') }}\nConfidence: {{ $json.ModerationLabels.map(l => l.Confidence.toFixed(1)).join(', ') }}"
  }
}

Error handling: Wrap Slack node in a Error Trigger to retry on rate limits (429) with exponential backoff.

6b. Safe Content Workflow

For images passing the filter:

  • Move or copy the object into a “public” S3 bucket or CDN origin.
  • Invoke downstream workflows (e.g., thumbnail generation, metadata extraction).
  • Send event to analytics or content pipelines.

// AWS S3 Move object (Copy + Delete)
Operation: Copy
Source Bucket: {{ $json.bucket }}
Source Key: {{ $json.key }}
Destination Bucket: my-app-public-images
Destination Key: {{ $json.key }}

// Then Delete original
Operation: Delete
Bucket Name: {{ $json.bucket }}
Key: {{ $json.key }}

7. Error Handling and Retry Logic

Wrap each AWS node with a Error Trigger node. On errors like timeouts or 5xx, configure up to three retries with backoff:

// Pseudocode for retry
if (error.retryable) {
  wait exponential( base=200, factor=2, attempts<=3 )
  retry node
} else {
  send alert email to [email protected]
}

Use n8n’s Error Workflow to centralize failure handling: log errors to a DynamoDB table, send Slack alerts, and pause the problematic event.

Testing & Output

Verifying the pipeline under multiple scenarios ensures reliability. Let’s simulate uploads, validate outputs, and confirm correct routing.

1. Safe Image Scenario

  1. Upload a mild image (e.g., landscape photo) to my-app-image-uploads/user123/landscape.jpg.
  2. SNS→n8n triggers. Rekognition returns empty ModerationLabels array.
  3. Workflow copies image to my-app-public-images/user123/landscape.jpg and logs success.
  4. Check destination bucket; confirm file is accessible with expected HTTP response (200 OK) and correct thumbnails.
$ aws s3 ls s3://my-app-public-images/user123/
2023-07-10 14:22:30      128045 landscape.jpg

2. NSFW Image Scenario

    1. Upload an explicit image nsfw.png.
    2. Rekognition returns labels:
{
  "ModerationLabels": [
    { "Name": "Explicit Nudity", "Confidence": 95.4 }
  ]
}
  1. n8n routes to flagged path: Slack channel receives a message. DynamoDB logs a new review job.
  2. Verify DynamoDB record with status = "pending_review".

3. Threshold Tuning

Test at multiple confidence levels (50, 70, 90). Plot false positives vs. false negatives. For user-facing platforms, you may prefer more manual slots—use a lower threshold like 50% and escalate ambiguous results for human review.

4. Edge Cases

    • Corrupted images: S3 Get returns error 400. Workflow catches error, sends to Dead Letter Queue (DLQ) for offline analysis.
    • Large files (>5 MB): Rekognition has 5 MB limit via binary buffer. For larger, store to S3 and use S3 reference mode:
// Rekognition node config
Image Parameter Type: S3Object
Bucket: {{ $json.bucket }}
Key: {{ $json.key }}
  • File type mismatch: .svg or unsupported formats. Reject early with Function node checking mimeType.

5. Monitoring and Metrics

Integrate CloudWatch metrics for Rekognition calls (Throttles, Latency) and SQS depth (if you use SQS). Use n8n’s execution logs for per-workflow duration. Set alarms for average processing time > 500ms or error rate > 1% over a 5-minute window.

Advanced Configuration

This section explores optimization, customization, and enterprise considerations.

1. Custom Confidence Calibration

    • Use adaptive thresholds based on category: Nudity vs. Violence. For example, require 90% confidence for “Suggestive” but 70% for “Graphic Violence.”
    • Implement in a Function node:
const labels = $json.ModerationLabels;
const safe = labels.every(label => {
  if (label.Name.includes('Suggestive')) return label.Confidence < 90;
  if (label.Name.includes('Violence')) return label.Confidence < 70;
  return label.Confidence < 80;
});
return [{ json: { safe } }];

2. Bulk Processing with SQS

For high-volume pipelines, replace SNS with S3→SQS event notifications. Use n8n’s AWS SQS Trigger node to poll in batches. This adds:

  • Visibility timeout and dead-letter queue for failed messages.
  • Batch size tuning to maximize throughput.
  • Parallel n8n workers with concurrency control.

3. Custom Model Integration

Augment Rekognition with custom moderation models (Amazon SageMaker). Deploy a custom image classification endpoint. In n8n:

  1. HTTP Request node: invoke SageMaker endpoint with base64 image payload.
  2. Parse JSON response with labels like “weapon,” “drugs,” or “hate symbols.”
  3. Merge results with Rekognition data and apply unified policy.
// HTTP Request node
URL: https://runtime.sagemaker.us-east-1.amazonaws.com/endpoints/moderation-endpoint/invocations
Method: POST
Headers: { "Content-Type": "application/json" }
Body: {
  "instances": [{ "bytes": "{{ binary.data.data.toString('base64') }}" }]
}

4. Rate Limiting and Throttling

  • Rekognition has soft limits (30 TPS). Monitor Throttles metric and back off on 429s.
  • Implement a Wait node between parallel branches to throttle burst traffic.
  • Leverage AWS API Gateway as a fronting layer to buffer and throttle requests into n8n.

5. Security Best Practices

  • Use IAM role chaining with minimal privileges. Rotate keys regularly.
  • Enforce TLS for all n8n endpoints. Apply OAuth or API key filters on webhooks.
  • Enable S3 bucket policies to allow only SNS publish events. Block public access.
  • Encrypt DynamoDB tables and SQS queues with KMS CMKs.

6. Auditing and Compliance

For regulated industries, store moderation decisions and raw labels in an audit database (e.g., RDS or DynamoDB) with immutable logging. Include user ID, timestamp, image checksum (SHA256), Rekognition response, and final decision. Use AWS CloudTrail to track API calls. This ensures you can demonstrate compliance with content policies.

Conclusion

You’ve built a robust, real-time image moderation pipeline using n8n and AWS Rekognition. We covered each step: from S3 event configuration and IAM setup, through workflow construction, to advanced topics like custom models and enterprise scaling. You now have a turnkey solution that detects NSFW content, routes flagged items for review, and automates notifications—keeping your platform safe and compliant.

Next steps:

  • Integrate text moderation (Amazon Comprehend or custom NLP) for image captions and comments.
  • Extend to video moderation using Rekognition Video APIs and media processing workflows.
  • Develop a moderator dashboard with React or Vue, pulling audit logs and metadata via GraphQL or REST.
  • Implement A/B testing on confidence thresholds to optimize human review effort.

Deploy this pipeline in production, monitor performance, and iterate on policy rules based on real-world data. With this foundation, you can confidently scale user-generated content features while protecting your community and brand.

FAQs

What are the costs associated with AWS Rekognition moderation?

AWS Rekognition pricing is per image or per minute for videos. As of this writing, moderation labels cost $1.00 per 1,000 images processed. Additional costs include S3 storage, SNS/SQS messaging (charged per million requests), and DynamoDB or SES usage for notifications. Always use the AWS Pricing Calculator and monitor your actual usage with Cost Explorer. For high volume, reserve throughput or negotiate an Enterprise Discount Program (EDP) with AWS.

How do I handle very large images (>5 MB)?

Binary payload limits apply when sending image bytes directly to Rekognition from n8n. For files >5 MB, switch Rekognition to S3Object mode. The node configuration changes to reference the bucket and key rather than binary data. This offloads the file to S3 and supports files up to Rekognition’s maximum (15 MB). Adjust IAM policies accordingly to allow rekognition:DetectModerationLabels on S3 objects.

How can I secure the n8n webhook endpoint that receives SNS events?

By default, n8n webhooks are publicly accessible URLs. To secure them, you can:
1. Use API Gateway in front of n8n, with an API key or JWT authentication.
2. Enable Basic Auth in n8n Webhook node settings.
3. Whitelist the SNS service IP ranges in a firewall or security group.
4. Verify the SNS signature in a Function node before processing the message.

Can I run this workflow on-premises or in another cloud?

Yes. n8n can be self-hosted anywhere (on-prem, AWS EC2, Azure, GCP). Rekognition is an AWS service, so you’ll need an AWS account and network access to the Rekognition API. Use AWS Direct Connect or VPN for private connectivity. If you want a fully on-premise moderation solution, consider running an open-source model (e.g., YOLO-based NSFW classifiers) within a Node.js custom node in n8n.

How do I scale this pipeline for thousands of images per minute?

Follow these practices:
1. Use SQS with batch processing and multiple n8n worker instances.
2. Shard SQS queues by customer or region to avoid hot partitions.
3. Monitor Rekognition’s Throttles metric and request service limit increases.
4. Use AWS Lambda or Step Functions for parallel orchestration if n8n becomes a bottleneck.
5. Enable auto-scaling on n8n deployment (Kubernetes HPA, ECS Service Autoscaling).

What alternatives exist for AWS Rekognition?

Other managed moderation APIs include:
1. Google Cloud Vision API (SafeSearch Detection).
2. Microsoft Azure Content Moderator.
3. Open-source libraries: nsfwjs, DeepAI NSFW Detector.
Trade-offs: managed services provide higher accuracy, SLA, and support for multiple content types, whereas open-source may require model hosting and ongoing maintenance.

Snehasish Konger
Developed @scientyficworld.org | Technical writer @Nected | Content Developer
Connect with Snehasish Konger

On This page

Take a Pause with Intervals

A Sunday letter on building, writing, and thinking deeper as a developer — short, honest, and worth your time.

Snehasish Konger profile photo

"Hey there — I'm Snehasish. Hope this post saved you some head-scratching time! I've spent years turning technical chaos into clarity, and I'm here to be your guide through the maze of modern tech. Stick around for more lightbulb moments — we're just getting started."

Related Posts