DEV Community

Ikoh Sylva
Ikoh Sylva

Posted on

Building Real-Time File Upload Notifications with S3 and SNS

How to wire Amazon S3 to Amazon SNS so that every file backed up to the cloud sends an instant email notification serverless, scalable, and set up in under 20 minutes.


This project building a simple file backup system with S3 event notifications publishing directly to an SNS topic is one of the most practical patterns in AWS. You'll find it in compliance systems, data ingestion pipelines, media processing platforms, and anywhere that teams need instant visibility into what's landing in their cloud storage.

Image of coloful laptop

"The best backup system is the one you trust. And trust starts with knowing your backup actually ran."


SNS vs Lambda (Choosing the Right Tool)

Both SNS and Lambda can receive S3 events. Here's how to think about which one belongs in your architecture:

SNS Direct Lambda Function
Code required None Yes
Fan-out to multiple recipients Built-in Manual (SES per recipient)
Best when The notification is the action The event triggers business logic
Subscribers Email, SMS, HTTP, SQS, Lambda One function (can fan out internally)
Setup time ~15 minutes ~30–60 minutes

For a backup notification system, SNS direct is the clear winner. We don't need to process the event we need everyone who cares to know it happened. That's pub-sub, and SNS is AWS's native pub-sub service.


The Architecture (Four Services, One Flow)

πŸ“€ Client (uploads file) β†’ πŸͺ£  S3 Bucket (detects s3:ObjectCreated event) β†’ πŸ“£  SNS Topic (publishes message to all subscribers) β†’ πŸ“¬  Subscribers (email / SMS / SQS / HTTP simultaneously)
Enter fullscreen mode Exit fullscreen mode

S3 fires an event the moment an object is created. That event is published to an SNS topic, which then fans out the notification to every subscriber simultaneously. One upload, one SNS message but potentially dozens of recipients each getting it in parallel.

SNS subscriber types you can attach:

  • Email β€” team inboxes, ops alerts
  • SMS β€” on-call phone alerts
  • HTTP/S β€” webhooks, Slack, Microsoft Teams
  • SQS Queue β€” async downstream processing
  • Lambda β€” custom logic as a downstream step

Step 1 β€” Create the S3 Bucket

This bucket will act as your backup destination. Navigate to S3 β†’ Create bucket.

  • Name it something descriptive: yourname-file-backups
  • Choose a region β€” record it, all resources must be in the same region
  • Under Bucket versioning, enable it β€” this protects against accidental overwrites
  • Leave Block all public access enabled β€” backup buckets should never be public

βœ… Enable versioning on backup buckets. Versioning means that if a file is overwritten or deleted, the previous version is preserved. For backup use cases, this is critical without it, a bad upload can silently destroy the data you were trying to protect.

Lifecycle rules for cost management (Optional)

While not required for the notification system, lifecycle rules are worth setting up alongside it. Navigate to Management β†’ Lifecycle rules β†’ Create lifecycle rule.

  • Transition objects to S3 Standard-IA after 30 days (40% cheaper for infrequently accessed data)
  • Transition to S3 Glacier Flexible Retrieval after 90 days (up to 85% cheaper for archival)
  • Set expiration on non-current versions after 90 days to avoid paying for old backup versions indefinitely

πŸ’‘ The backup cost equation: S3 Standard costs $0.023/GB/month. S3 Glacier costs $0.004/GB/month. For long-lived backups, automated lifecycle transitions can reduce storage costs by 80–95% with zero manual intervention and your notification system still fires on every upload.


Step 2 β€” Create the SNS Topic

Navigate to SNS β†’ Topics β†’ Create topic.

  • Type: Standard (not FIFO, S3 event notifications do not support FIFO SNS topics)
  • Name: s3-backup-notifications
  • Leave all other settings as default
  • Click Create topic

Copy the Topic ARN from the topic details page: it looks like arn:aws:sns:us-east-1:123456789012:s3-backup-notifications. You'll need it in the next two steps.

⚠️ Standard topic only (FIFO is not supported). S3 event notifications cannot deliver to Amazon SNS FIFO topics. If you accidentally create a FIFO topic (name ending in .fifo), S3 will fail to save the notification configuration. Always use Standard topics for S3-triggered notifications.


Step 3 β€” Configure the SNS Access Policy

This is the step most tutorials gloss over and where most people hit their first error. S3 cannot publish to your SNS topic until you explicitly grant it permission via a resource-based policy on the topic.

In your SNS topic, go to Edit β†’ Access policy. Replace the default policy with this:

{
  "Version": "2012-10-17",
  "Id": "s3-backup-sns-policy",
  "Statement": [
    {
      "Sid": "AllowS3ToPublish",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:REGION:ACCOUNT_ID:s3-backup-notifications",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:::yourname-file-backups"
        },
        "StringEquals": {
          "aws:SourceAccount": "YOUR_AWS_ACCOUNT_ID"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

πŸ” Anatomy of this policy: The ArnLike condition restricts publishing to only your specific S3 bucket preventing any other bucket (even in your own account) from sending messages to this topic. The StringEquals on aws:SourceAccount is a defence-in-depth measure against confused deputy attacks (a scenario where a bucket in another account tricks your topic into accepting their events.) Together: "Only my bucket, in my account, can publish here."


A cool Image

Step 4 β€” Subscribe to the SNS Topic

In your SNS topic, click Create subscription.

  • Protocol: Email
  • Endpoint: your email address
  • Click Create subscription

SNS immediately sends a confirmation email. You must click the confirmation link before the subscription becomes active. Until confirmed, the subscription shows as PendingConfirmation and will not receive any notifications.

βœ… Add multiple subscribers for team visibility. You can add as many email subscribers as you need your entire ops team, a shared inbox, a monitoring alias. Each subscriber is independent: adding or removing one doesn't affect the others. Each subscription requires its own confirmation click.


Step 5 β€” Configure S3 Event Notifications

Navigate to your S3 bucket β†’ Properties β†’ Event notifications β†’ Create event notification.

  • Event name: BackupFileUploaded
  • Prefix (optional): e.g. backups/ to only trigger on files in that folder
  • Suffix (optional): e.g. .zip to only trigger on compressed archives
  • Event types: check All object create events (covers Put, Post, Copy, CompleteMultipartUpload)
  • Destination: SNS topic
  • SNS topic: select or paste the ARN of your topic
  • Click Save changes

⚠️ If you see "Unable to validate the destination" error: S3 tried to send a test message to your SNS topic and was rejected. Almost always this is the access policy from Step 3 either the bucket ARN in the ArnLike condition doesn't match the actual bucket name, or the account ID is wrong.

πŸ’‘ Use prefix and suffix filters strategically. If your bucket stores multiple types of content, filters save you from notification noise. A database dump (.sql.gz) warrants a notification. A temporary log file being written mid-process probably doesn't.


Step 6 β€” Test the Full Pipeline

Upload any file to your bucket via the console, CLI, or any tool that writes to S3:

# Upload a test backup file via CLI
aws s3 cp ./my-database-backup.sql.gz \
    s3://yourname-file-backups/backups/

# Verify it's there
aws s3 ls s3://yourname-file-backups/backups/
Enter fullscreen mode Exit fullscreen mode

Within seconds, your subscribed email should receive a notification. The raw JSON payload S3 sends through SNS looks like this:

{
  "Records": [{
    "eventVersion": "2.1",
    "eventSource": "aws:s3",
    "eventName": "ObjectCreated:Put",
    "eventTime": "2025-01-15T09:23:41.000Z",
    "s3": {
      "bucket": { "name": "yourname-file-backups" },
      "object": {
        "key": "backups/my-database-backup.sql.gz",
        "size": 4096000,
        "eTag": "d41d8cd98f00b204e9800998ecf8427e"
      }
    }
  }]
}
Enter fullscreen mode Exit fullscreen mode

πŸŽ‰ Your backup notification system is live. Every file that lands in your S3 bucket now triggers an instant notification. No Lambda to maintain, no polling to configure, no server to manage. The system scales to millions of uploads without any changes on your end.


Troubleshooting Common Issues

S3 can't save the event notification "Unable to validate destination"

The SNS topic policy isn't granting S3 permission to publish. Check that the bucket ARN in the ArnLike condition exactly matches your bucket name. Note: S3 ARNs don't include a region or account ID it's just arn:aws:s3:::bucket-name.

Confirmation email never arrived

Check spam. SNS confirmation emails frequently land in junk folders. If it's not there after a few minutes, go to SNS β†’ Subscriptions, find yours in PendingConfirmation state, and click Request confirmation to resend it.

Upload happens but no email received

Confirm the subscription status in SNS β†’ Subscriptions. If it still shows PendingConfirmation, the confirmation link was never clicked. If Confirmed, verify the S3 event notification was saved correctly under S3 β†’ Properties β†’ Event notifications.

Receiving too many notifications / notification noise

Add prefix or suffix filters to your S3 event notification to scope it down. Alternatively, route notifications to an SQS queue first and batch or filter there before forwarding to email.


Real-World Extensions of This Pattern

This S3 β†’ SNS pipeline is a foundation, not a ceiling. Once the plumbing is in place, here's how production teams extend it:

  • Multi-destination fan-out β€” Add an SQS queue as a second subscriber: email goes to the ops team, the queue feeds an automated validation workflow checking file integrity
  • Slack / Teams integration β€” Subscribe an HTTP/S endpoint to the SNS topic, pointing at a Slack incoming webhook, for real-time channel alerts without email
  • Cross-account notifications β€” SNS topics can notify subscribers in other AWS accounts useful for centralising backup alerts in a dedicated monitoring account in an AWS Organisations setup
  • Compliance audit trails β€” Store the SNS event messages in an SQS queue, then archive them to S3 Glacier an immutable, timestamped record that every backup ran, when it ran, and how large it was

What I Learned From This Project

It teaches pub-sub thinking at exactly the right level of simplicity.

A few things that genuinely resonated:

  • SNS access policies are resource-based, not identity-based β€” just like S3 bucket policies, SNS topic policies are attached to the resource, not the caller. S3 presents as a service principal (s3.amazonaws.com), and the policy must explicitly grant that principal permission.
  • The confused deputy attack is real, not theoretical β€” the aws:SourceAccount condition exists because without it, any S3 bucket in the world could potentially publish to your SNS topic if they knew its ARN. Scoping by account prevents that. Scoping by bucket ARN tightens it further. Both conditions together that's defence in depth.
  • Fan-out changes how you think about notifications β€” before SNS, "notify someone" meant "send them an email." After SNS, "notify" means "publish once, let the subscribers decide what to do." One upload, many outcomes, none of them coupled to each other.
  • Versioning and notifications are complementary, not redundant β€” versioning protects the data; notifications protect the process. Together they answer two different questions: "Is the file safe?" and "Did it arrive?"

Quick Reference: Services and Their Roles

# Services in this project

S3 bucket           β†’ backup storage; fires s3:ObjectCreated events on upload
S3 versioning       β†’ preserves previous file versions (overwrites, deletions)
S3 lifecycle rules  β†’ auto-transitions to cheaper storage classes over time
SNS Standard topic  β†’ receives S3 events; fans out to all active subscribers
SNS access policy   β†’ grants s3.amazonaws.com permission to sns:Publish
SNS subscription    β†’ email (or SMS, SQS, HTTP) endpoint; must be confirmed

# The event chain
File uploaded to S3 β†’ S3 publishes JSON event to SNS topic β†’ SNS fans out to all confirmed subscribers simultaneously β†’ Email arrives within seconds
Enter fullscreen mode Exit fullscreen mode

Cool Image

I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps & Cloud Job Placement / Mentorship Program.

For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.

Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.

This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.

Do refer below for the link with a dedicated discount automatically applied at checkout;

DevOps & Cloud Job Placement / Mentorship Program.

If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;

Apply here or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!

Special Offer: By signing up through the link and using the code shared, you’ll receive a 10% discount!

Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.

I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.

If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.

Let’s connect on social media. I’d love to engage and exchange ideas with you!

LinkedIn Facebook X


Top comments (0)