In this final section, we'll explore how to test and deploy our complete serverless e-commerce solution and discuss some key considerations for the project.
Before deploying the application to production, it's essential to thoroughly test it to ensure that all components work together correctly.
Testing the Infrastructure
To test the AWS CDK infrastructure, we can use the cdk synth
Command to generate the CloudFormation template and verify that it's correct:
# Navigate to the CDK project directory
cd serverless-ecommerce-cdk
# Synthesize the CloudFormation template
cdk synth
This command will generate a cdk.out/ServerlessEcommerceStack.template.json
file that we can examine to verify that all resources are configured correctly.
Testing Lambda Functions
To test Lambda functions locally, we can use the AWS SAM framework:
# Install AWS SAM CLI
npm install -g aws-sam-cli
# Navigate to the Lambda function directory
cd lambda/semantic-search
# Create a test event file
cat > event.json << EOF
{
"queryStringParameters": {
"query": "black t-shirt size L"
}
}
EOF
# Run the Lambda function locally
sam local invoke -e event.json
Testing the MCP Server
To test the MCP server locally, we can use Docker:
# Navigate to the MCP server directory
cd docker/mcp-server
# Build the Docker image
docker build -t mcp-server .
# Run the container
docker run -p 3000:3000 \
-e COMMERCE_LAYER_SECRET_ARN=your-secret-arn \
-e STRAPI_SECRET_ARN=your-secret-arn \
-e AWS_REGION=us-east-1 \
mcp-server
Testing Strapi CMS
To test Strapi CMS locally, we can use Docker Compose:
# Navigate to the Strapi directory
cd docker/strapi-cms
# Copy the example configuration file
cp .env.example .env
# Edit the .env file with your configurations
# Start the containers
docker-compose up -d
End-to-End Testing
To perform an end-to-end test of the complete application, we can use a test script that simulates a user flow:
// test-e2e.js
const fetch = require('node-fetch');
async function testEndToEnd() {
console.log('End-to-End Test of the Serverless E-commerce Application');
// 1. Semantic search for products
console.log('\n1. Semantic search for products');
const searchQuery = 'black t-shirt size L';
const searchResponse = await fetch(`http://localhost:3000/api/search?query=${encodeURIComponent(searchQuery)}`);
const searchResults = await searchResponse.json();
console.log(`Results for "${searchQuery}":`);
searchResults.results.forEach((product, index) => {
console.log(`${index + 1}. ${product.name} - ${product.price} €`);
});
// 2. Get product details
console.log('\n2. Get product details');
const productId = searchResults.results[0].id;
const productResponse = await fetch(`http://localhost:3000/api/products/${productId}`);
const productDetails = await productResponse.json();
console.log('Product details:');
console.log(JSON.stringify(productDetails, null, 2));
// 3. Add product to cart
console.log('\n3. Add product to cart');
const cartResponse = await fetch('http://localhost:3000/api/cart', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
productId,
quantity: 1
})
});
const cart = await cartResponse.json();
console.log('Cart:');
console.log(JSON.stringify(cart, null, 2));
// 4. Checkout
console.log('\n4. Checkout');
const checkoutResponse = await fetch('http://localhost:3000/api/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
cartId: cart.id,
customer: {
email: 'test@example.com',
firstName: 'Test',
lastName: 'User'
},
shippingAddress: {
line1: '123 Main St',
city: 'New York',
zipCode: '10001',
stateCode: 'NY',
countryCode: 'US'
},
billingAddress: {
line1: '123 Main St',
city: 'New York',
zipCode: '10001',
stateCode: 'NY',
countryCode: 'US'
}
})
});
const order = await checkoutResponse.json();
console.log('Order created:');
console.log(JSON.stringify(order, null, 2));
console.log('\nEnd-to-End Test completed successfully!');
}
testEndToEnd().catch(console.error);
Production Deployment
Once we've tested the application and are confident that it works correctly, we can proceed with the deployment to production.
Deploying the AWS CDK Infrastructure
To deploy the AWS CDK infrastructure to production, we use the cdk deploy
command:
# Navigate to the CDK project directory
cd serverless-ecommerce-cdk
# Deploy the stack to production
cdk deploy --profile production
This command will create all the necessary AWS resources for our application, including Lambda functions, Fargate services, DynamoDB tables, API Gateway, etc.
Deploying Strapi CMS
To deploy Strapi CMS to production, we can use the Fargate service configured in our CDK stack:
# Build the Strapi Docker image
docker build -t strapi-cms ./docker/strapi-cms
# Tag the image for ECR
docker tag strapi-cms:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/strapi-cms:latest
# Log in to ECR
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
# Push the image to ECR
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/strapi-cms:latest
Deploying the MCP Server
To deploy the MCP server to production, we follow a similar process:
# Build the MCP server Docker image
docker build -t mcp-server ./docker/mcp-server
# Tag the image for ECR
docker tag mcp-server:latest ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-server:latest
# Push the image to ECR
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-server:latest
Deploying the Frontend
To deploy the frontend, we can use the S3 bucket and CloudFront distribution configured in our CDK stack:
# Build the frontend
cd frontend
npm run build
# Sync the files with the S3 bucket
aws s3 sync ./out s3://your-frontend-bucket-name --profile production
# Invalidate the CloudFront cache
aws cloudfront create-invalidation --distribution-id your-distribution-id --paths "/*" --profile production
Monitoring and Maintenance
Once the application is in production, it's important to monitor it and maintain it to ensure that it continues to function correctly.
Monitoring with CloudWatch
AWS CloudWatch allows us to monitor the performance and health of our application:
# Create a CloudWatch dashboard
aws cloudwatch put-dashboard --dashboard-name ServerlessEcommerce --dashboard-body file://cloudwatch-dashboard.json --profile production
Setting Up Alarms
We can configure CloudWatch alarms to be notified in case of problems:
# Create an alarm for API response time
aws cloudwatch put-metric-alarm \
--alarm-name ApiResponseTimeAlarm \
--alarm-description "Alarm for API response time" \
--metric-name Latency \
--namespace AWS/ApiGateway \
--statistic Average \
--period 300 \
--threshold 1000 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=ApiName,Value=ServerlessEcommerceApi \
--evaluation-periods 3 \
--alarm-actions arn:aws:sns:${AWS_REGION}:${AWS_ACCOUNT_ID}:ServerlessEcommerceAlarms \
--profile production
Data Backups
It's important to configure regular data backups:
# Enable automatic backups for DynamoDB
aws dynamodb update-continuous-backups \
--table-name ProductsTable \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true \
--profile production
Final Considerations
Scalability
Our serverless architecture is designed to scale automatically based on load. AWS Lambda and Fargate adapt to the number of requests, while DynamoDB can be configured to automatically scale read and write capacity.
Costs
One of the main advantages of serverless architecture is the pay-per-use cost model. We only pay for the resources we use, without fixed costs for idle servers. However, it's important to monitor costs and configure budgets and alarms to avoid surprises.
Security
Security is a fundamental aspect of any e-commerce application. We've implemented several security measures, including:
- Authentication and authorization with AWS IAM
- Encryption of data at rest and in transit
- Secure management of secrets with AWS Secrets Manager
- Input validation and protection against common attacks
Future Improvements
There are several improvements that could be made to our application in the future:
- Personalization: Use AWS Personalize to provide personalized recommendations to customers
- Data Analytics: Implement AWS Analytics to analyze user behavior and improve the shopping experience
- Internationalization: Add support for multiple languages and currencies
- Social Media Integration: Implement authentication and sharing on social media
- Mobile App: Develop a native mobile app for iOS and Android
Summary
In this tutorial, we've created a complete serverless e-commerce application for selling ServerlessDay merchandise, using:
- AWS CDK to define the infrastructure as code
- AWS Lambda and Fargate for serverless processing
- AWS Bedrock for semantic product search
- Strapi CMS for content management
- Commerce Layer for e-commerce logic
This architecture offers numerous advantages, including:
- Scalability: The application automatically adapts to load
- Optimized Costs: We only pay for the resources we use
- Reduced Maintenance: We don't have to manage servers or infrastructure
- Flexibility: We can easily add new features or modify existing ones
- Improved User Experience: Semantic search allows users to easily find the products they're looking for
By implementing this solution, we've created a modern, scalable, and easy-to-manage e-commerce platform that offers an excellent shopping experience for customers.
Useful Resources
- AWS CDK Documentation
- AWS Bedrock Documentation
- Commerce Layer Documentation
- Strapi Documentation
- AWS Security Guide
- Best Practices for Serverless Applications
With this, we conclude our tutorial on how to implement a serverless e-commerce solution with AWS Bedrock, Commerce Layer, and Strapi. We hope this guide has been helpful and has provided you with the knowledge needed to create your own serverless e-commerce solution.
Member discussion