Building a Scalable E-Commerce Platform with Next.js, Flutter, AWS, and NestJS
Discover how a modern e-commerce platform was architected and built using Next.js for the storefront, Flutter for cross-platform mobile apps, AWS for cloud infrastructure, and NestJS for backend microservices. This case study details the challenges of scaling to handle peak traffic, the goals of creating a seamless omnichannel experience, the architectural approach, implementation specifics, results achieved, key metrics, and lessons learned for future projects.
Case StudyE-CommerceNext.jsFlutterAWSNestJSScalabilityMicroservicesFull-Stack
Overview
ShopSphere is a next-generation e-commerce platform designed to deliver a seamless shopping experience across web and mobile channels.
The platform integrates product discovery, personalized recommendations, inventory management, secure payment processing,
order fulfillment, and customer service into a unified system.
By leveraging modern frontend technologies and a microservices backend, ShopSphere aims to provide high performance,
scalability, and maintainability while supporting rapid feature iteration.
The decision to adopt a headless architecture allowed the team to decouple the presentation layer from the core commerce
functionality, enabling independent evolution of web and mobile frontends.
This approach also facilitated easier integration with thirdâparty services such as marketing automation tools,
analytics platforms, and ERP systems.
The platform targets both B2C and B2B customers, offering features like bulk ordering, quote management,
and contractâbased pricing for wholesale clients.
Challenge
The primary challenges faced during the project were multifaceted.
First, the platform needed to handle extreme traffic spikes during flash sales and holiday seasons,
where concurrent users could surge from a few thousand to over one hundred thousand within minutes.
Second, delivering a consistent, highâfidelity user experience across diverse devices â ranging from desktop browsers
to lowâend Android smartphones â required careful performance budgeting and adaptive UI strategies.
Third, ensuring data consistency and low latency across a distributed microservices ecosystem proved complex,
especially for inventory levels that must be accurate to prevent overselling.
Fourth, integrating with a variety of thirdâparty APIs (payment gateways, shipping carriers, tax services)
while maintaining security and compliance with PCIâDSS and GDPR added another layer of complexity.
Finally, the team had to achieve these goals within a tight timeline and with a limited budget,
necessitating careful prioritization and efficient use of cloud resources.
Goals
The project set measurable objectives to gauge success.
The primary goal was to achieve an uptime SLA of 99.9% measured monthly,
with a target of fewer than 45 minutes of downtime per month.
A second goal was to support at least 100,000 concurrent users during peak events
without degrading response times beyond two seconds for API calls and page loads.
Third, the team aimed to reduce average page load time (LCP) to under 1.8 seconds on web
and under 2.0 seconds on mobile connections simulating 3G speeds.
Fourth, the architecture needed to enable independent deployment of services
through fully automated CI/CD pipelines, allowing multiple releases per day
with minimal manual intervention.
Fifth, realâtime inventory synchronization across all sales channels was required
to ensure that stock levels displayed to customers always reflected actual availability.
Lastly, the platform needed to support A/B testing and feature flagging
to facilitate dataâdriven decision making and rapid experimentation.
Approach
To address these challenges, the team adopted a domainâdriven design (DDD) methodology,
identifying bounded contexts for Catalog, Order, Payment, User, and Notification.
Each context was implemented as a separate NestJS microservice,
communicating via asynchronous messaging (Amazon SQS) for eventual consistency
and synchronous REST/gRPC for immediate consistency needs.
The frontend stack consisted of Next.js 13 for the web storefront,
leveraging its App Router, serverâside rendering (SSR), and incremental static regeneration (ISR)
to balance SEO, performance, and dynamic content.
For mobile, Flutter 3.7 was chosen for its expressive UI toolkit,
singleâcodebase advantage, and strong performance characteristics.
A dedicated GraphQL layer (Apollo Server) aggregated data from multiple microservices,
providing efficient data fetching and reducing overâfetching.
Infrastructure was defined as code using AWS CDK (TypeScript),
enabling reproducible environments and automated provisioning of networking,
compute, storage, and security resources.
Implementation
**Web Frontend (Next.js)**
The web storefront was built with Next.js 13, TypeScript, and Tailwind CSS.
Product listing pages used incremental static regeneration (ISR) with a revalidation window of 60 seconds,
allowing nearârealâtime updates while still benefiting from static generation.
Product detail pages employed serverâside rendering to ensure personalized data such as
customerâspecific pricing and loyalty discounts were always up to date.
The cart functionality was implemented using a combination of React Context and
HTTPâonly cookies storing an encrypted cart identifier,
which minimized exposure to crossâsite scripting (XSS) attacks.
Image optimization relied on the Next.js Image component, which automatically served
optimized formats (WebP, AVIF) and resized images based on the deviceâs viewport.
All static assets were uploaded to an S3 bucket and distributed via Amazon CloudFront
with origin access control (OAC) to prevent direct S3 access.
**Mobile Frontend (Flutter)**
The Flutter application targeted both iOS and Android from a single codebase.
State management was handled via the Bloc pattern,
which facilitated predictable state transitions and easy testing.
API communication was powered by a Dio client generated from OpenAPI specifications,
ensuring type safety and contract consistency between frontend and backend.
For push notifications, the app integrated Firebase Cloud Messaging (FCM)
to deliver timely order updates and promotional messages.
Biometric authentication (Face ID, Touch ID, Android BiometricPrompt)
was implemented using the local_auth plugin,
providing a secure and frictionless login experience.
To cope with intermittent connectivity, the app used Hive as a local database
to cache product catalogs and pending orders,
with a background sync service that reconciled changes when network connectivity resumed.
The UI adapted responsively to different screen sizes using Flutterâs Flexible and Expanded widgets,
and adaptive layout widgets ensured a native look and feel on each platform.
**Backend (NestJS Microservices)**
Each microservice was built with NestJS 9, TypeScript, and TypeORM for data access.
The Catalog service managed product information, categories, and attributes,
storing data in an Amazon RDS PostgreSQL instance.
The Order service handled cart conversion, order placement, payment initiation,
and order status transitions, publishing events to an SNS topic for downstream processing.
The Payment service wrapped thirdâparty gateways (Stripe, PayPal, Adyen)
and emitted success/failure events to reconcile orders.
The User service managed profiles, addresses, and authentication,
issuing JWT access tokens and refresh tokens via secure HTTPâonly cookies.
The Notification service consumed events from SNS and dispatched emails via Amazon SES,
SMS via Amazon SNS, and inâapp notifications via WebSocket gateway.
All services were containerized with Docker and deployed to Amazon ECS (Fargate)
with autoâscaling policies based on CPU and memory utilization.
Interâservice communication used a combination of REST (for synchronous calls)
and Amazon SQS queues (for asynchronous event processing),
with deadâletter queues configured to capture failed messages for inspection.
**Infrastructure and DevOps**
Infrastructure was provisioned using AWS CDK (TypeScript),
which allowed the team to define VPCs, subnets, security groups, IAM roles,
and other resources in a versionâcontrolled manner.
The architecture spanned multiple availability zones for high availability.
Amazon RDS PostgreSQL was configured with MultiâAZ deployment and read replicas
to offload readâheavy workloads such as product browsing and search.
Amazon ElastiCache (Redis) provided distributed caching for session stores,
rate limiting counters, and frequently accessed product lists.
Amazon API Gateway acted as the single entry point for all client requests,
enforcing JWT authorization, rate limiting (burst and rate),
and AWS WAF rules to block common exploits such as SQL injection and XSS.
Continuous integration and delivery were implemented with GitHub Actions:
workflows ran linting (ESLint), unit tests (Jest), integration tests (SuperTest),
built Docker images, pushed them to Amazon Elastic Container Registry (ECR),
and triggered rolling updates to ECS services.
Monitoring and observability were achieved through Amazon CloudWatch
(metrics, logs, alarms) and AWS XâRay for distributed tracing,
enabling the team to pinpoint latency bottlenecks and error spikes in real time.
Results
Following a phased rollout that began with a closed beta and expanded to full public launch,
ShopSphere delivered measurable improvements over the legacy platform.
Uptime averaged 99.95% during the first three months postâlaunch,
exceeding the 99.9% SLA target and translating to less than 22 minutes of downtime per month.
During a Black Friday flash sale, the platform successfully handled 120,000 concurrent users,
with average API response times of 210âŻms and page load times (LCP) of 1.4âŻseconds on web
and 1.6âŻseconds on mobile (simulated 3G).
Conversion rate rose from 3.1% on the old system to 3.8% on ShopSphere,
representing a 22% relative increase.
Cart abandonment decreased from 68% to 58%, a 15% improvement attributed to
the streamlined checkout flow and guest checkout option.
Operational overhead, measured as the number of manual interventions per release,
dropped by approximately 30% due to automated deployments, selfâhealing infrastructure,
and comprehensive health checks.
Customer satisfaction scores (CSAT) increased from 78% to 86% based on postâpurchase surveys.
Metrics
Key performance indicators tracked after launch included:
- **Uptime**: 99.95% (target â„ 99.9%)
- **Peak Concurrent Users**: 120,000 (target â„ 100,000)
- **Average API Response Time (p95)**: 210âŻms
- **Web Largest Contentful Paint (LCP)**: 1.4âŻseconds
- **Mobile LCP (3G simulation)**: 1.6âŻseconds
- **Conversion Rate**: 3.8% (legacy: 3.1%)
- **Cart Abandonment Rate**: 58% (legacy: 68%)
- **Deployment Frequency**: Average of 1.2 releases per day
- **Mean Time to Recovery (MTTR)**: 12 minutes
These metrics demonstrated that the platform not only met but exceeded its initial goals.
Lessons Learned
Several important lessons emerged from the project that will guide future endeavors.
First, investing in contract testing early â using tools like Pact or Dredd to validate
API interactions between frontend and backend â prevented many integration issues
that would have surfaced only in staging or production.
Second, adopting a blueâgreen deployment strategy for critical services
allowed the team to release new versions with zero downtime and instant rollback
capability if anomalies were detected.
Third, feature flags (implemented via LaunchDarkly) proved invaluable for
experimenting with new UI flows and backend algorithms;
they enabled safe experimentation in production and quick rollback when metrics
indicated regressions.
Fourth, establishing clear observability from day one â distributing tracing,
centralized logging, and realâtime dashboards â made it far easier to
identify performance bottlenecks and error spikes during highâtraffic events.
Fifth, defining explicit ownership boundaries for each microservice,
while maintaining shared governance for crossâcutting concerns such as security
and logging, helped prevent the âhot potatoâ problem where no team felt responsible
for a particular service.
Sixth, establishing performance budgets for both frontend (page size, script weight)
and backend (API latency, database query times) guided optimization efforts
and prevented regressions as the codebase evolved.
Finally, fostering a culture of blameless postmortems encouraged engineers
to share openly about failures, leading to continuous improvement of processes
and systems.
Future Outlook
Looking ahead, the team plans to integrate machine learningâbased recommendation engines using Amazon Personalize, expand to additional marketplaces via multiâtenant architecture, and explore progressive web app (PWA) enhancements to further blur the line between web and mobile experiences. These initiatives aim to keep ShopSphere at the forefront of eâcommerce innovation.