This guide provides step-by-step instructions for deploying the portfolio data processing solution.
Before deploying, ensure you have:
-
AWS Account
- Active AWS account with billing enabled
- IAM user with AdministratorAccess or appropriate permissions
-
AWS CLI
# Install AWS CLI pip install awscli # Configure credentials aws configure
-
Terraform
# MacOS brew install terraform -
Python 3.11+
python3 --version
git clone <repository_url>
# Install Python dependencies (optional, for local testing)
make install
# or
pip install -r requirements.txtCreate a infrastructure/terraform.tfvars file:
aws_region = "us-east-1"
environment = "staging"
bucket_name = "portfolio-data-staging-YOUR-UNIQUE-SUFFIX"Important: S3 bucket names must be globally unique. Replace YOUR-UNIQUE-SUFFIX with something unique.
cd infrastructure
terraform initExpected output:
Initializing the backend...
Initializing provider plugins...
Terraform has been successfully initialized!
terraform plan --var-file="staging.tfvars"This shows what resources will be created:
- 1 S3 bucket
- 2 Lambda functions
- 1 DynamoDB table
- 2 SQS queues
- IAM roles and policies
- CloudWatch log groups
- S3 event notifications
terraform apply --var-file="staging.tfvars"Type yes when prompted to confirm.
Deployment takes approximately 2-3 minutes.
After successful deployment, note the outputs:
terraform outputSave these values:
s3_bucket_name- For uploading CSV filessqs_queue_url- For reading messagescoordinator_lambda_arn- For monitoringprocessor_lambda_arn- For monitoring
Example:
s3_bucket_name = "staging-portfolio-data-abc123"
sqs_queue_url = "https://sqs.us-east-1.amazonaws.com/123456789/staging-portfolio-messages"
Use the Makefile command:
make upload-test-dataOr manually:
BUCKET_NAME=$(terraform -chdir=infrastructure output -raw s3_bucket_name)
aws s3 cp example_data/clients_20200130.csv s3://$BUCKET_NAME/
aws s3 cp example_data/portfolios_20200130.csv s3://$BUCKET_NAME/
aws s3 cp example_data/accounts_20200130.csv s3://$BUCKET_NAME/
aws s3 cp example_data/transactions_20200130.csv s3://$BUCKET_NAME/Watch the coordinator Lambda logs:
aws logs tail /aws/lambda/staging-csv-coordinator --followWatch the processor Lambda logs:
aws logs tail /aws/lambda/staging-csv-processor --followQUEUE_URL=$(terraform -chdir=infrastructure output -raw sqs_queue_url)
aws sqs receive-message \
--queue-url $QUEUE_URL \
--max-number-of-messages 10 \
--attribute-names AllExpected output includes messages like:
{
"type": "client_message",
"client_reference": "9e40659b-8b9f-4fc4-814b-5a7b5a23b64",
"tax_free_allowance": 801,
"taxes_paid": 0
}aws dynamodb scan \
--table-name staging-file-tracking \
--output tableSymptom: Files uploaded but no messages in SQS
Solutions:
-
Check S3 event notification configuration:
aws s3api get-bucket-notification-configuration \ --bucket $BUCKET_NAME -
Verify Lambda has S3 invoke permission:
aws lambda get-policy \ --function-name staging-csv-coordinator
-
Check CloudWatch logs for errors
Symptom: "Error creating S3 bucket: BucketAlreadyExists"
Solution: Change bucket_name in terraform.tfvars to a unique value
Symptom: "Error creating Lambda function: InvalidParameterValueException"
Solution: Ensure Python source files exist in src/ directory
Symptom: Lambda executes successfully but no messages
Solutions:
- Check processor Lambda logs for errors
- Verify all 4 CSV files were uploaded for the same date
- Check DynamoDB table to confirm all files marked present
- Ensure CSV files have correct format and headers
Symptom: "AccessDenied" errors in Lambda logs
Solutions:
- Verify IAM roles have correct policies attached
- Check bucket policy allows Lambda access
- Ensure SQS queue policy allows SendMessage
Create a CloudWatch dashboard to monitor:
- Lambda invocation count and errors
- Lambda duration and throttles
- SQS message count and age
- DynamoDB read/write capacity
Set up CloudWatch alarms for:
# Lambda errors
aws cloudwatch put-metric-alarm \
--alarm-name staging-processor-errors \
--alarm-description "Alert on Lambda errors" \
--metric-name Errors \
--namespace AWS/Lambda \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--dimensions Name=FunctionName,Value=staging-csv-processorLogs are retained for 7 days by default. To change:
# In infrastructure/main.tf
resource "aws_cloudwatch_log_group" "processor_logs" {
retention_in_days = 30 # Change to 30 days
}- Modify Python files in
src/ - Run:
terraform apply
Terraform detects code changes and updates Lambda functions.
- Modify Terraform files
- Run:
terraform plan # Review changes terraform apply
To remove all resources and stop charges:
# Delete all objects from S3 bucket first
aws s3 rm s3://$BUCKET_NAME --recursive
# Destroy infrastructure
cd infrastructure
terraform destroyType yes to confirm.
Warning: This permanently deletes all data and resources.
Estimated monthly costs for moderate usage (assuming 30 days, 1 upload/day):
| Service | Usage | Estimated Cost |
|---|---|---|
| Lambda | 60 invocations, 1GB-sec | $0.00 (Free Tier) |
| S3 | 120 files, 10MB each | $0.03 |
| SQS | 120 requests | $0.00 (Free Tier) |
| DynamoDB | 120 writes, 240 reads | $0.00 (Free Tier) |
| CloudWatch | 1GB logs | $0.50 |
| Total | ~$0.53/month |
Note: Costs increase with:
- Higher upload frequency
- Larger file sizes
- More downstream consumers reading from SQS
- Longer log retention
Before deploying to production:
- Change
environmentvariable to "prod" - Use unique bucket name with "prod" prefix
- Enable S3 bucket logging
- Enable AWS CloudTrail
- Configure CloudWatch alarms
- Set up AWS Backup for DynamoDB
- Implement VPC endpoints for private networking
- Add KMS encryption for S3 and SQS
- Configure reserved Lambda concurrency
- Set up AWS Config for compliance
- Create runbook for incident response
- Test disaster recovery procedures
- Review and tighten IAM policies
- Enable AWS GuardDuty for threat detection
For issues or questions:
- Check CloudWatch Logs for error messages
- Review this deployment guide
- Consult the main README.md
- Check AWS Service Health Dashboard