{"id":24461068,"url":"https://github.com/oxide-byte/todo-serverless","last_synced_at":"2025-05-06T00:10:16.202Z","repository":{"id":223937813,"uuid":"757119884","full_name":"oxide-byte/todo-serverless","owner":"oxide-byte","description":"Simple AWS Serverless Todo application, containing Rust Lambda functions, Rust Leptos static frontend and deployed with a SAM CloudFormation template","archived":false,"fork":false,"pushed_at":"2024-03-29T19:45:35.000Z","size":2875,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T01:03:13.772Z","etag":null,"topics":["aws","aws-lambda","cloudformation","dynamodb","leptos","leptos-rs","rust","s3-website","sam","serverless","wasm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxide-byte.png","metadata":{"files":{"readme":"readme.adoc","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-13T21:01:42.000Z","updated_at":"2024-09-14T10:24:26.000Z","dependencies_parsed_at":"2024-03-13T10:03:41.882Z","dependency_job_id":null,"html_url":"https://github.com/oxide-byte/todo-serverless","commit_stats":null,"previous_names":["oxide-byte/todo-serverless"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxide-byte%2Ftodo-serverless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxide-byte%2Ftodo-serverless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxide-byte%2Ftodo-serverless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxide-byte%2Ftodo-serverless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxide-byte","download_url":"https://codeload.github.com/oxide-byte/todo-serverless/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252596422,"owners_count":21773845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-lambda","cloudformation","dynamodb","leptos","leptos-rs","rust","s3-website","sam","serverless","wasm"],"created_at":"2025-01-21T04:17:16.638Z","updated_at":"2025-05-06T00:10:16.187Z","avatar_url":"https://github.com/oxide-byte.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Todo Serverless\n\n== WARNING\n\nimage::.readme-resources/aws_ec2_joke.jpeg[]\n\nThis project is deployed on the AWS Cloud and like each Cloud service it could generate costs. Even when parts are covered by the https://aws.amazon.com/free/[AWS Free Tier] it is your responsibility to evaluate and survey costs that also may change over time.\n\nWhile reading different documentations and forums, the following hint I found useful:\n\n- Consider to use 2 way authenticated. (Be aware, hacker could use your account for example for crypto mining and generate high costs).\n\n- Consider not to use your root account as working user, but to create a second account.\n\n- Consider to create a Budget plan, even only to 1€, and receive a [NOTIFICATION-MAIL] when the limit is reached.\n\n- Consider to remove all resources not needed or created for testing.\n\n== Content\n\nThis project contains a POC implementation for an Serverless application. The following elements could be found in the project\n\n\n* Makefile : scripts building and deploying the application\n\n* SAM (template.yaml) containing the Cloud Formation definition for the AWS Serverless environment. it deploys\n\n** 5 Lambda Functions build on Rust for the different GET/PUT/POST/DELETE operations\n\n** A DynamoBB storing the data for the application\n\n** An S3 Bucket with public access containing a static Web Site build on Leptos\n\n** A CloudWatch group containing the logs of the application\n\n** Api Gateway for CORS, Policies, Usage Plan,... to configure the elements\n\nimage::.readme-resources/schema.png[]\n\n== Requirement\n\nFor deploying the application we need:\n\n* an AWS account\n\n* an AWS User with programmatic Access Keys for SAM.\n\n* AWS SAM configured with the Access Keys for deploying the application\n\n* a Rust development environment as the functions are build on Rust (Rust compiler and cargo)\n\n* Trunk (WASM) for building the Rust Leptos Frontend\n\n* A critical and open mind :smile: Don't simply copy/paste, this code it is more for inspiration and showcase. It works (on my pc :grin:)\n\n== Deployment\n\nThe deployment is partially automated, this due the SAM that manages the serverless application and the scripts prepared in the Makefile.\n\nHere the steps:\n\n1) Modifying in the template.yaml file the bucket name. It must be unique on the cloud:\n\n```\n  S3Bucket:\n    Type: AWS::S3::Bucket\n    DeletionPolicy: Delete\n    Properties:\n      # REPLACE THIS NAME BY YOUR OWN BUCKET NAME !!!\n      # APPLY ALSO THE NAME IN THE [MakeFile]:\n      #   BUCKET_NAME := todo-app-xxx\n      BucketName: todo-app-xxx\n```\n\n2) From Makefile the step: api\n\nit compiles the lambda functions and deploys it to AWS with creating and configuring the AWS Serverless application, including Bucket and DynamoDB\n\n3) On the end you get in the output the URL for the Lambda function. !!! ATTENTION !!! these entry points are public. So ANYBODY could, when known sent requests on it. The TodoUsagePlan and CORS would be some of the elements to consider for reducing risks.\n\n```\n2024-02-21 20:29:04 - Waiting for stack create/update to complete\n\nCloudFormation events from stack operations (refresh every 5.0 seconds)\n-------------------------------------------------------------------------------------------------\nResourceStatus           ResourceType             LogicalResourceId        ResourceStatusReason\n-------------------------------------------------------------------------------------------------\nCREATE_COMPLETE          AWS::Logs::LogGroup      TodoLogGroup             -\nCREATE_COMPLETE          AWS::DynamoDB::Table     TodoDB                   -\nCREATE_COMPLETE          AWS::IAM::Role           TodoExecutionRole        -\nCREATE_COMPLETE          AWS::Lambda::Function    TodoEditItemFunction     -\nCREATE_COMPLETE          AWS::Lambda::Function    TodoDeleteItemFunction   -\nCREATE_COMPLETE          AWS::Lambda::Function    TodoAddItemFunction      -\nCREATE_COMPLETE          AWS::Lambda::Function    TodoGetItemFunction      -\nCREATE_COMPLETE          AWS::Lambda::Function    TodoGetListFunction      -\nCREATE_COMPLETE          AWS::S3::Bucket          S3Bucket                 -\nCREATE_COMPLETE          AWS::ApiGateway::RestA   ServerlessRestApi        -\nCREATE_COMPLETE          AWS::S3::BucketPolicy    BucketPolicy             -\nCREATE_COMPLETE          AWS::Lambda::Permissio   TodoDeleteItemFunction   -\nCREATE_COMPLETE          AWS::Lambda::Permissio   TodoAddItemFunctionCat   -\nCREATE_COMPLETE          AWS::Lambda::Permissio   TodoGetListFunctionCat   -\nCREATE_COMPLETE          AWS::Lambda::Permissio   TodoGetItemFunctionCat   -\nCREATE_COMPLETE          AWS::Lambda::Permissio   TodoEditItemFunctionCa   -\nCREATE_COMPLETE          AWS::ApiGateway::Deplo   ServerlessRestApiDeplo   -\nCREATE_COMPLETE          AWS::ApiGateway::Stage   ServerlessRestApiProdS   -\nCREATE_COMPLETE          AWS::ApiGateway::Usage   TodoUsagePlan            -\nCREATE_COMPLETE          AWS::CloudFormation::S   todo-app                 -\n\nCloudFormation outputs from deployed stack\n-------------------------------------------------------------------------------------------------\nOutputs\n-------------------------------------------------------------------------------------------------\nKey                 TodoBucketUrl\nDescription         S3 Bucket URL:\nValue               https://XXXXXXXXXXXXXXXXX.s3.eu-west-1.amazonaws.com\n\nKey                 TodoGetListFunctionAPI\nDescription         API [get-todos] URL:\nValue               https://XXXXXXXXXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/Prod/get-todos\n```\n\nThe points could already be used by CURL or in the folder http some scripts, if you use IntelliJ Ultimate.\n\n4) Before building the Frontend, we need to modify the URL on to access on the API entry points. In todo_ui/src/components/todo_service.rs replace the URL:\n\n```\nTodoService {\n    url: \"https://XXXXXXXXXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/Prod/\".to_string()\n}\n```\n\nAlso replace in the Makefile the Bucket for publishing the static files:\n\n```\nSTACK_NAME ?= todo-app\nFUNCTIONS := get-todos\nBUCKET_NAME := todo-demo-xxx\n```\n\n5) From the Makefile you can now executing the step: ui that build and deploys the web components in the S3 Bucket. !!! ATTENTION !!!The same here, the URL is public accessible.\n\n6) Accessing the application from the Bucket URL, you find it in the logs of the SAM deployment (https://XXXXXXXXXXXXXXXXX.s3.eu-west-1.amazonaws.com)\n\n*CLEAN UP*\n\nWhen you are finished, you can remove the resources with the step clean in Makefile. Validate the logs, and ensure that all resources have been deleted in connecting to the AWS console.\n\n== Components\n\nLet take a look on the different components created:\n\n=== S3 Bucket\n\nimage::.readme-resources/s3.png[]\n\nIn the S3 Bucket we would find the uploaded files (HTML, JS, CSS) that forms the static web page.\n\nimage::.readme-resources/s3_url.png[]\n\nLooking on the properties, we would also find here the URL to access the application by a web browser.\n\nimage::.readme-resources/s3_sam.png[]\n\nYou see also a bucket containing the Cloud Formation template uploaded with the SAM commands from Makefile. A link to S3 pricing: https://aws.amazon.com/s3/pricing/\n\n=== Cloud Formation\n\nimage::.readme-resources/cloud_formation.png[]\n\nIt provides the Todo project description. it could be modified inside AWS, but the changes would not be at that time on your template.yaml\n\nimage::.readme-resources/cloud_formation_diagram.png[]\n\nYou can also access it with the visual editor to look and modify elements.\n\n=== AWS Lambda\n\nimage::.readme-resources/lambda_dashboard.png[]\n\nOn the AWS Lambda screen, we see the currently number of Lambda's installed. to mention, we see the current 5 Lambda's only use 15 MB (3MB per Lambda). One advantage of Rust Lambda's, they are compact.\n\nimage::.readme-resources/lambda.png[]\n\nIn details, we see the lambda's. As we see, the names would change each time you clean and install your SAM, but not when updating a SAM Project. A link to Lambda pricing: https://aws.amazon.com/lambda/pricing/\n\n=== DynamoDB\n\nimage::.readme-resources/dynamo_db.png[]\n\nThe DynamoDB created and storing the Todo's of the application. A link to the Dynamo pricing: https://aws.amazon.com/dynamodb/pricing/\n\n=== Cloud Watch\n\nimage::.readme-resources/cloudwatch_group.png[]\n\nIn Cloud Watch the generated Log Group\n\nimage::.readme-resources/cloudwatch_log_lambda.png[]\n\nContaining for each function a group of logs\n\nimage::.readme-resources/cloudwatch_time_price.png[]\n\nand looking on the log entry, we see the memory and billing duration defining the costs of this single execution. Here also we see 55ms with an allocation of 128MB Memory is competitive. A link to Cloudwatch pricing: https://aws.amazon.com/cloudwatch/pricing/\n\n=== API Gateway\n\nimage::.readme-resources/api_gateway.png[]\n\nFor the last, take a look on the API Gateway showing the different entry points, linked to the different Lambda functions, and also containing the CORS definition. The API Gateway will also generate costs, see: https://aws.amazon.com/api-gateway/pricing/[]\n\n== Conclusion\n\nThis sample was for me the continuation of my Todo series, on Serverless. After the implementation:\n\n* Serverless is not a silver bullet, it is one of many ways to solve a problem. Analyse the problem and choose the right tool. But learning new tools, to know about your options.\n\n* I think I would on a real project favorite CDK (with TypeScript) over SAM for creating and deploying the Cloud Formation. I used AWS Code Whisperer to support me on creating the template.yaml, with TypeScript I would be supported by auto-complete by my IDE.\n\n* The Frontend part I would not store on S3 but looking for solutions to avoid the CORS problems. Also in mindset that Leptos provide a better solution with server side rendering.\n\n* I will keep my researches and studies with Rust as language for Lambda's. But today already a lot of Lambda functions are written in other languages and these also search for solutions to reduce the cold start and to reduce costs. So your Serverless journey is not bound to a language and keep an eye on projects like https://github.com/awslabs/llrt[LLRT].\n\n== Disclaimer\n\nThis GitHub project is experimental application for education purpose. It's important to acknowledge that cloud services could generate costs based on usage, configuration, and external factors.\n\nBy accessing and utilizing this project, you agree that:\n\n    Cost Management Responsibility: You are responsible for monitoring and managing the costs associated with deploying and running this application in your own cloud environment. This includes understanding the pricing structure of the cloud service provider and making informed decisions to optimize costs.\n\n    Usage and Deployment: You acknowledge that the usage and deployment of this application may result in charges from the cloud service provider. It's essential to review and comprehend the pricing details provided by the cloud service provider before deploying the application.\n\n    No Liability: The creators and contributors of this project are not liable for any costs incurred as a result of deploying, running, or modifying this application. This includes, but is not limited to, charges accrued from cloud services, unexpected usage spikes, or misconfigurations.\n\n    Best Practices and Recommendations: We strongly recommend implementing cost management best practices, such as setting up budget alerts, utilizing cost-effective resources, and regularly reviewing usage reports to avoid unexpected expenses.\n\n    Continuous Monitoring: It's your responsibility to continuously monitor the usage and costs associated with running this application. Periodic reviews of cloud billing statements and resource utilization are essential to ensure cost-effectiveness.\n\n    Feedback and Contributions: We welcome feedback and contributions to enhance the efficiency and cost-effectiveness of this project. However, any changes made to optimize costs should be thoroughly tested to ensure they do not compromise the functionality or security of the application.\n\nBy proceeding with the usage of this project, you acknowledge that you have read, understood, and agreed to the terms outlined in this disclaimer. If you do not agree with these terms, refrain from accessing or utilizing this project.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxide-byte%2Ftodo-serverless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxide-byte%2Ftodo-serverless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxide-byte%2Ftodo-serverless/lists"}