Juan Rodríguez

Project Farms

This project is a personal SaaS for farm management, designed to help farmers efficiently manage their operations. It allows users to register operators, food, treatments, suppliers, customers, and also record events related to animals such as purchases, sales, mounts, births, deaths, feeding, treatments, etc.
The frontend is built with React, TypeScript, Tailwind CSS, Radix UI, providing a responsive and user-friendly interface.
The backend is powered by AWS Lambda functions, enabling serverless architecture for scalability and cost-efficiency. API Gateway is used to manage and secure API endpoints, while RDS hosts the relational database for storing user data and content. User authentication is handled by AWS Cognito, ensuring secure access to the platform.
There is also a chatbot integrated into the system using AWS Bedrock Agents and Pinecone, which provides users with assistance and support, enhancing the overall user experience.
Overall, this project demonstrates my ability to design and implement a full-stack application using modern web technologies and AWS services. This project is composed of 13 stacks that handle different parts of the application, from user authentication to content delivery.
The design structure of the application is organized into several layers, including the database layer, backend layer, and frontend layer. It also includes important components such as the authentication system, event handling, idempotency and content management, all of which work together to provide a seamless user experience.

URL: farms.juancrs.com

Design structure
          
Users AWS Cloud CloudFront farms.juancrs.com RDS PostgreSQL Rest Api Lambdas Consumer Proxy Website VPC Cognito User Pool WAF CloudWatch BedRock Agent BedRock SQS SES

CDK / Infrastructure

This code snippet demonstrates how to set up a database stack. It includes the creation of a VPC, security groups, and an RDS instance. The roles to be used by Lambdas to access the database are also defined here. Also included Lambda functions to initialize the database with a user and permissions and function to create tables on the database. The initialize function is triggered via a custom resource to ensure it runs after the RDS instance is created. The function to create tables is also defined and should be invoked as needed from AWS Console or other mechanisms.

    
export class DatabaseStack extends Stack { constructor(scope: Construct, id: string, props: WebStackProps) { super(scope, id, props); // Step 1: Create a VPC and security groups for the RDS instance and Lambda functions // The VPC will provide network isolation for the RDS instance and Lambda functions, ensuring that they can only communicate with each other and not be accessed from the public internet // We will create separate security groups for the RDS instance and Lambda functions to control the traffic between them // The security group for the RDS instance will allow inbound traffic on the PostgreSQL port (5432) only from the security group of the Lambda functions // Also add Interface VPC Endpoints for Secrets Manager and SQS to allow private communication between the Lambda functions and these services without going through the public internet // Step 2: Create a Role for the RDS instance // Allow to rds.amazonaws.com to write logs to CloudWatch and add Metrics. // Step 3: Create an RDS PostgreSQL instance // Create a subnet group for the RDS instance that includes the private subnets of the VPC // Create the RDS instance with the following configuration: // - Engine: PostgreSQL // - Instance type: db.t3.micro (suitable for development and testing, can be changed for production) // - Storage: 20 GB (can be adjusted based on needs) // - Credentials: RDS will automatically generate secrets for the database. // - VPC and security groups: Place the RDS instance in the VPC and associate it with the security group created for it // Step 4: Grant the RDS Role permissions to read the database credentials from the RDS instance secret. // Step 5: Grant the RDS Role permissions to read the database credentials from the Secrets Manager secret created in your AWS account. // Step 6: Create a Role for the Lambda functions // This role will be assumed by the Lambda functions that need to access the RDS instance // Grant this role permissions to read the database credentials from both the RDS instance secret and the Secrets Manager secret // Also grant permissions to connect to the RDS instance using the rds:Connect action, specifying the ARN of the RDS instance // Additionally, grant permissions for VPC access like creating and managing network interfaces, describing subnets, security groups, and route tables to allow the Lambda functions to operate within the VPC // Step 7: Instantiate a Lambda Layer that includes the necessary libraries to connect to the PostgreSQL database. // This layer will be used by the Lambda functions that need to access the RDS instance, allowing us to manage dependencies in a centralized way and keep the Lambda function code clean. // Step 8: Create a Lambda function to initialize the database with a user and permissions. // This function will be responsible for creating a new database user with the necessary permissions to access the database and perform operations on it. // The function will be triggered via a custom resource to ensure it runs after the RDS instance is created. // Step 9: Create another Lambda function to create tables on the database. // This function can be invoked as needed from AWS Console or other mechanisms to set up the database schema. // Outputs: You can add CfnOutput to share the RDS Endpoint or other resources if needed } }