A React + TypeScript project demonstrating different approaches to file upload concurrency control using AWS S3 with LocalStack for local development.
This project explores three distinct concurrency patterns for file uploads to S3:
- Sequential Upload - complexity with blocking phases
- Async Batch Upload - complexity with parallel processing within phases
- Streaming Upload - complexity with real-time progress tracking and mutex protection
Each implementation showcases different levels of concurrency control, from basic sequential processing to advanced streaming with race condition management using async-mutex.
- Frontend: React 19 + TypeScript + Vite
- AWS SDK: @aws-sdk/client-s3 + @aws-sdk/s3-request-presigner
- Concurrency: async-mutex for race condition management
- Local Infrastructure: LocalStack + Docker + Nginx (CORS proxy)
- Development: ESLint + TypeScript strict mode
src/
├── infra/
│ ├── S3Client.ts # LocalStack S3 client configuration
│ └── crypto.ts # MD5 integrity checking utilities
├── useCases/
│ ├── useSequentialUpload.ts # Sequential upload implementation
│ ├── useAsyncBatchUpload.ts # Batch async upload implementation
│ └── useStreamingUpload.ts # Streaming upload with mutex protection
├── types/
│ └── uploadProgress.ts # Unified progress tracking interfaces
├── blog/
│ ├── PT-BR.md # Portuguese technical article
│ └── EN-US.md # English technical article
├── App.tsx # Main application with centralized file display
└── main.tsx # Application entry point
- Node.js (18+)
- Docker & Docker Compose
- npm or yarn
-
Clone and install dependencies:
git clone <repo-url> cd frontend-concurrency-control npm install
-
Start LocalStack infrastructure:
docker-compose up -d
This starts:
- LocalStack S3 service on port 4566
- Nginx CORS proxy for frontend access
-
Start development server:
npm run dev
Application will be available at
http://localhost:5173
npm run dev- Start development servernpm run build- Build for productionnpm run lint- Run ESLintnpm run preview- Preview production build
The project uses LocalStack to simulate AWS S3 locally:
- Endpoint:
http://localhost:4566 - Region:
us-east-1 - Credentials:
test/test(development only) - Default Bucket:
test-uploads
Nginx proxy handles CORS issues between the frontend and LocalStack:
- Frontend requests go to
localhost:4566(Nginx) - Nginx proxies to LocalStack with proper CORS headers
- Supports file uploads up to 100MB
- Pre-signed URLs for secure uploads
- MD5 integrity checking with Content-MD5 headers
- File validation and size limits
- Start the application: Follow the Development Setup steps above
- Select files: Use the file input to choose multiple files
- Choose strategy: Select from "Sequential", "Batch (Async)", or "Streaming" upload
- Run test: Click the upload button and observe the performance
- Monitor progress: For streaming uploads, watch real-time file-by-file progress
- Compare results: Switch strategies and run again to compare performance
- View metrics: Check the results table for detailed timing comparisons and percentage improvements
- Ensure Docker is running:
docker ps - Check LocalStack logs:
docker-compose logs localstack - Verify bucket creation: Check LocalStack dashboard
- Nginx proxy should handle CORS automatically
- Verify nginx container is running:
docker-compose ps
- Check network connectivity to LocalStack
- Verify pre-signed URL generation
- Check file size limits (100MB max)
- Browser connection limits affect batch performance
- LocalStack resource constraints in Docker
- Network saturation with many concurrent uploads
- async-mutex: Race condition management for concurrent operations
- crypto-js: MD5 hash generation for file integrity
- @aws-sdk/client-s3: AWS S3 client for bucket operations
- @aws-sdk/s3-request-presigner: Pre-signed URL generation