Serverless8 min read

    Building a Production-Ready Serverless File Sharing Platform on AWS

    Tarek Cheikh

    Founder & AWS Cloud Architect

    Serverless file sharing platform architecture on AWS

    How I built a secure, scalable file sharing solution using AWS Lambda, API Gateway, and Cognito — with zero infrastructure to manage

    Your team needs a secure way to share files with external partners. You could use a third-party service, but you need full control over your data. You could build a traditional server-based solution, but that means managing infrastructure, scaling issues, and security headaches.

    What if you could build an enterprise-grade file sharing platform that scales automatically, costs pennies to run, and requires zero infrastructure management?

    That's exactly what I built with SmallFileSharing — and today, I'm sharing the blueprint with you.

    The Challenge

    In my consulting work at Toc Consulting, I frequently encounter enterprises that need:

    • Complete data sovereignty — files must stay in their AWS accounts
    • Enterprise-grade security — with proper authentication and authorization
    • Cost efficiency — no paying for idle servers
    • Scalability — from 10 to 10,000 users without code changes
    • Email notifications — because not everyone checks apps constantly

    Traditional solutions either lack features, cost too much, or require significant operational overhead.

    The solution? Go serverless.

    Architecture That Scales

    Here's the beauty of serverless architecture — every component automatically scales.

    Serverless file sharing platform architecture diagram showing API Gateway, Lambda, S3, DynamoDB, Cognito, and SES

    Why These Services?

    AWS Cognito: Handles user authentication with zero code. It provides:

    • JWT tokens for stateless authentication
    • User registration and password reset flows
    • Multi-factor authentication support

    AWS Lambda: Executes our business logic without servers:

    • Pay only for execution time (milliseconds!)
    • Automatic scaling from 0 to thousands of concurrent requests
    • No patching, no maintenance

    DynamoDB: Tracks file metadata with predictable performance:

    • Single-digit millisecond latency at any scale
    • Automatic backups and encryption

    S3: Stores the actual files with 99.999999999% durability:

    • Automatic encryption at rest
    • Lifecycle policies for cost optimization

    SES: Sends sharing notifications reliably:

    • High deliverability rates
    • Detailed tracking and analytics

    Key Design Decisions

    1. Base64 Encoding for Simplicity

    Yes, I chose to base64-encode files in the API payload. Why?

    {
        "file_data": "iVBORw0KGgoAAAANSUhEUgAAB0QAAANi...",
        "remote_file_name": "document.pdf"
    }
    • Simplicity: No multipart form handling needed
    • Compatibility: Works with any HTTP client
    • Trade-off: Limited to 10MB files (API Gateway limit)

    For larger files, I'd implement direct S3 uploads with presigned URLs — but for 90% of business documents, 10MB is plenty.

    2. JWT-Based Authorization

    Every Lambda function validates the JWT token and checks ownership:

    def is_user_authorized(user_id, event):
        '''Check if the user is authorized to access the file'''
        url_user_id = event['path'].split('/')[3]
        file_id = event['path'].split('/')[5]
    
        if url_user_id != user_id:
            return False, None
    
        is_owned_by_user, file_infos = is_file_owned_by_user(user_id, file_id)
        if not is_owned_by_user:
            return False, None
    
        return True, file_infos

    This ensures users can only access their own files — critical for multi-tenant scenarios.

    3. Time-Limited Sharing Links

    When sharing files, the system generates presigned S3 URLs that expire after 1 hour:

    s3_client = boto3.client('s3', conf_values['REGION'])
    response = s3_client.generate_presigned_url(
        'get_object',
        Params={
            'Bucket': bucket_name,
            'Key': file_path
        },
        ExpiresIn=3600  # 1 hour
    )

    This provides security without complexity — no need for recipient accounts or passwords.

    Real-World Implementation

    Here's how the file sharing flow works:

    1. Upload a File

    POST /v1/users/{user_id}/files
    
    Payload:
    
    {
      "file_data": "base64_encoded_data",
      "remote_file_name": "document.pdf"
    }
    
    Response:
    {
        "file_id": "70ffa2f2-b106-4cbc-86c6-d5bab6959dcd",
        "status": "UPLOADED"
    }

    The Lambda function:

    • Validates the JWT token
    • Decodes the base64 file data
    • Stores it in S3 under {user_id}/{filename}
    • Records metadata in DynamoDB

    2. Share with Email

    POST /v1/users/{user_id}/files/{file_id}/share
    
    {
        "share_with": ["partner@company.com"]
    }

    The magic happens here:

    • Generate a presigned S3 URL
    • Send a beautifully formatted email via SES
    • Recipients get a secure link that works for 1 hour

    3. Automatic Cleanup

    Files can be deleted programmatically:

    DELETE /v1/users/{user_id}/files/{file_id}

    This removes both the S3 object and DynamoDB record — keeping storage costs minimal.

    The Cost Advantage

    Let's talk numbers. For a typical usage pattern (1000 files/month, 5MB average):

    Traditional Server Approach:

    • EC2 instance (t3.medium): ~$30/month
    • Load balancer: ~$20/month
    • Database: ~$15/month
    • Total: ~$65/month minimum

    Serverless Approach:

    • Lambda: ~$0.50
    • API Gateway: ~$3.50
    • S3 storage: ~$1.15
    • DynamoDB: ~$0.25
    • Total: ~$5.40/month

    That's a 91% cost reduction — and it scales linearly with usage!

    Security Best Practices Implemented

    1. Input Validation: JSON schemas validate every request
    2. Authentication: JWT tokens expire and must be refreshed
    3. Authorization: Row-level security ensures data isolation
    4. Encryption: Data encrypted at rest and in transit
    5. Audit Trail: CloudWatch logs every action for compliance

    Lessons Learned

    After deploying this in production environments, here are my key takeaways:

    1. Start simple: Base64 encoding isn't elegant, but it works and ships fast
    2. Embrace managed services: Let AWS handle the undifferentiated heavy lifting
    3. Design for failure: Every Lambda includes comprehensive error handling
    4. Monitor everything: CloudWatch dashboards catch issues before users do
    5. Document extensively: Your future self will thank you

    Try It Yourself

    The complete source code is available on GitHub under the MIT license: TocConsulting/small-file-sharing

    Quick Start:

    1. Clone the repository
    2. Deploy the CognitoApi dependency
    3. Follow the README steps
    4. Import the Postman collection
    5. Start sharing files securely!

    What's Next?

    I'm actively working on:

    • Terraform templates for one-click deployment
    • Support for larger files via multipart upload
    • End-to-end encryption options
    • Admin dashboard for monitoring

    Final Thoughts

    Serverless isn't just about cost savings — it's about focusing on what matters: solving business problems instead of managing infrastructure.

    This file sharing platform handles production workloads for multiple enterprises, costs almost nothing to run, and required zero infrastructure decisions beyond the initial architecture.

    The future of enterprise applications is serverless. Are you ready to make the jump?

    Found this helpful? Give the GitHub repository a star and share this article with your network!

    Go Deeper: The State of AWS Security 2026

    This article is just the start. Get the full picture with our free whitepaper - 8 chapters covering IAM, S3, VPC, monitoring, agentic AI security, compliance, and a prioritized action plan with 50+ CLI commands.

    AWS LambdaServerlessS3API GatewayDynamoDB