Is Serverless Monolith a good or bad thing?
In the serverless community, there is a continuous discussion regarding the choice between utilizing fat functions, also referred to as serverless monoliths, or single-purpose functions in the design of AWS Lambda architectures. This conversation focuses on key factors, compromises, and top methods for serverless applications.
The Case for Single-Purpose Functions
Supporters of single-purpose functions argue that this approach enhances security and reduces overhead. By assigning specific IAM roles to each function, developers can limit permissions precisely, minimizing potential security risks. Additionally, having distinct functions for different workloads prevents unnecessary dependencies. For example, if a function handles both service rendering and REST API tasks, separating these responsibilities ensures that only necessary dependencies are loaded, improving efficiency.
However, single-purpose functions can introduce complexity, especially when migrating from monolithic applications. Many customers transitioning from large Express.js apps to Lambda may find it challenging to restructure their codebases into multiple functions immediately.
The Value of Fat Functions (Serverless Monoliths)
Fat functions, or serverless monoliths, offer a simpler initial migration path. By encapsulating existing monolithic applications within a single Lambda function, teams can quickly leverage serverless benefits without extensive refactoring. This approach is particularly useful when dealing with frameworks like Express.js, which can run inside a Lambda function.
Yet, fat functions come with their own set of challenges. Over time, as the application scales and more developers get involved, the initial simplicity can lead to maintenance and operational difficulties. The cognitive load on the team increases, making onboarding and collaboration more complex. Additionally, some third-party providers charge based on the number of unique Lambda functions, potentially leading to higher costs if functions are not consolidated effectively.
A Balanced Approach
The best strategy often lies in balancing the two approaches. Start with a fat function to quickly migrate and establish a working baseline. This allows teams to organize their ideas, understand their operational boundaries, and identify shared code. As the application evolves, break down the fat function into smaller, single-purpose functions, focusing on security and efficiency.
This gradual transition helps manage the cognitive load on the team and allows for a more flexible and adaptable architecture. The key is to find a middle ground that accommodates the specific needs of the application and the team’s workflow.
Practical Considerations
When deciding between fat functions and single-purpose functions, consider the following:
- Security: Single-purpose functions offer better security through tailored IAM roles.
- Operational Overhead: Fat functions reduce initial complexity but may increase maintenance efforts over time.
- Cost: Third-party provider costs can influence function design, especially if charged per unique function.
- Development Speed: Fat functions can speed up initial development and migration.
- Team Dynamics: Consider the cognitive load on the team and the ease of onboarding new developers.
Governance and Observability
Managing multiple Lambda functions versus a single monolithic Lambda involves different levels of effort, especially in governance and observability.
Multiple Lambda Functions (Microservices)
Benefits:
- Independent Development: Teams can develop, test, and deploy functions separately, speeding up the process.
- Specific Scalability: Each function can scale on its own, using resources more efficiently.
- Fault Isolation: Problems in one function don’t affect others, making the system more resilient.
Challenges:
- Complex Governance: Managing security policies, access control, and compliance for each function can be complicated.
- Difficult Observability: Monitoring and debugging multiple functions is challenging, as you need to collect and correlate data from different places.
- Complex Deployments: Setting up and managing CI/CD pipelines for multiple functions requires good automation.
Serverless Monolith (Monolithic Lambda)
Benefits:
- Simple Governance: Easier to manage security and compliance for a single unit.
- Centralized Observability: Easier to monitor and debug with centralized logs, metrics, and traces.
- Unified Deployments: One CI/CD pipeline simplifies the deployment process.
Challenges:
- Scalability Issues: Scaling a single function can be less efficient, potentially creating bottlenecks.
- Complex Code: As the application grows, the code can become harder to maintain.
- High Risk of Changes: Changes can impact the entire system, requiring thorough testing and validation.
Conclusion
There is no one-size-fits-all answer to the fat function vs. single-purpose function debate. Every method comes with advantages and disadvantages, so the most suitable option will vary based on the application’s context and the team’s requirements. Beginning with a comprehensive function and then transitioning towards specialized functions allows teams to find a harmony that optimizes security, productivity, and manageability.