Multi-Tenant Merchant Platform

Problem:
FTP ingress was a bottleneck with frequent downtime, costing clients money.
Solution:
Built a 99.99% available multi-tenant SFTP gateway with automated AWS provisioning.
Impact:
Zero unplanned downtime; supports 500+ merchants simultaneously.
Overview
Multi-tenant SFTP ingress with automated provisioning and strong isolation so merchant onboarding doesn't compromise reliability.
Results & metrics
- 99.99% platform availability
- $40k/year AWS cost reduction
- 500+ merchants with zero unplanned downtime
- Automated tenant provisioning in <5 minutes
Before / after
Ingress reliability
Before: Fragile FTP paths, painful incidents
Scale
Before: Onboarding friction for new tenants
Tenant Security
Before: Shared storage buckets risking cross-tenant data exposure
What I built
Chroot-jailed SFTP gateway
Merchants share one SFTP gateway on EC2, each jailed to its own folder by chroot.
Automated tenant provisioning
A supplier's new feed auto-creates user, password and chroot, in under 5 minutes.
VPC endpoints for S3
S3 traffic moved off the NAT Gateway onto VPC endpoints; AWS costs fell $40k/year.
Stack
- AWS Transfer Family, SFTP
- Amazon S3, with KMS Encryption
- AWS Lambda, Ingestion Router
- Amazon DynamoDB
- Terraform IaC
Decisions
Key trade-offs and design calls that shaped the final delivery.
EC2 over managed SFTP
Why
- Context
- AWS Transfer Family was expensive for multi-tenant use case with many users
- Decision
- Self-managed SFTP on EC2 with custom user isolation logic using chroot—significantly lower cost for high user count
chroot over containerization
Why
- Context
- Needed lightweight isolation without Docker overhead on a single EC2 instance
- Decision
- Linux-level chroot jails with chmod for directory restrictions—simpler, lower resource footprint than containers
Architecture
The primary system boundaries, runtime pieces, and how the project was structured in production.
- External Merchants → AWS Transfer SFTP Gateway
- AWS Transfer SFTP Gateway → IAM Role & Key Authentication
- IAM Role & Key Authentication → DynamoDB Tenant Registry
- AWS Transfer SFTP Gateway → Lambda Ingestion Router
- Lambda Ingestion Router → S3 Bucket: Tenant Prefixes
- Lambda Ingestion Router → SQS Batch Queue
- SQS Batch Queue → Payment Settlement Workers
- Payment Settlement Workers → S3 Processed Archive
- AWS EC2 SFTP Server
FTP Gateway
How
Self-managed SFTP on EC2 with chroot jail isolation—merchants and suppliers connect to shared infrastructure with strict boundaries.
- chroot + chmod
Tenant Isolation
How
Linux-level chroot jails enforce directory boundaries—merchants cannot escape their dedicated folders, access controlled at OS level.
- Auto-generated credentials
Credential Management
How
1 supplier can have multiple merchants. Only suppliers can create passwords and users. Custom feed creation generates user/password pairs auto-assigned to respective tenant directories, shareable with specific suppliers.
Mermaid source
Paste into mermaid.live to edit the diagram.
flowchart TB
subgraph Client [Merchant Ingestion]
M[External Merchants]
SFTP[AWS Transfer SFTP Gateway]
end
subgraph Routing [Tenant Isolation & Metadata]
AUTH[IAM Role & Key Authentication]
DYNAMO[(DynamoDB Tenant Registry)]
ROUTER[Lambda Ingestion Router]
end
subgraph Storage [Encrypted Object Store]
S3RAW[(S3 Bucket: Tenant Prefixes)]
S3PROC[(S3 Processed Archive)]
end
subgraph Pipeline [Downstream Settlement]
SQS[SQS Batch Queue]
WORKER[Payment Settlement Workers]
end
M --> SFTP
SFTP --> AUTH
AUTH --> DYNAMO
SFTP --> ROUTER
ROUTER --> S3RAW
ROUTER --> SQS
SQS --> WORKER
WORKER --> S3PROCPipeline
How changes moved from development through validation and deployment.
Auto-create user, password, and chroot environment per tenant with proper permissions
Single instance serving all tenants with resource monitoring and SSH access for management
chmod/chroot enforce boundaries at OS level—merchants cannot access other directories
Select a step for its detail
Incidents
Operational failures, rehearsals, or recovery moments that changed how the system was run.
- P1
API endpoints exposed without authentication
Resolution
Implemented private API authentication and integrated with backend for proper access control
Lesson: All APIs must be authenticated by default—never assume internal-only access is safe
- P2
Backend integration breaking on user creation
Resolution
Standardized API contracts and added validation for supplier-merchant relationship creation
Lesson: Multi-tenant systems need strict relationship validation between entities