Where should I run my applications?
Well, it depends...how large is your application, how complex or legacy it it, and what are your scaling needs?
We will see examples looking at Google Cloud options and making some comparisons with AWS Cloud.
In a way, it's a trade-off: the more power and flexibility you want, the more responsibility and complexity you have to manage. It's like moving from a small, simple rented flat where you live in a bedroom, sharing with others, to a high-customized detached house you’ve built from scratch with your designs. The first option is getting less involved but can’t get customization, and the second requires engagement and work to obtain personalization.
As people say in Spain, «no hay pescao grande y que pese poco», which translates to "There is no big fish that weighs little”. The more you want from a solution—whether it’s power, control, or customization—the more effort you’ll need to put into managing it.
It is indeed an interesting irony that as your cloud needs grow, so does the complexity of managing the infrastructure. When you start with small or simple applications, serverless options like Cloud Functions or AWS Lambda are incredibly appealing because they require minimal management. You don't need to worry about the underlying infrastructure; everything is handled for you, making it easy to scale small workloads. However, as your applications grow in complexity or scale, you often find yourself needing more control (and saving money…).
Unmanaged services (from the provider’s perspective)
Unmanaged services are those where you have more control over the infrastructure and are responsible for managing it yourself. This may include setting up, configuration, maintenance, patches, updates, scaling, and security.
You get to fine-tune and customize it to your liking, but it also comes with the responsibility of regular maintenance and handling potential issues.
Google Compute Engine
Using Virtual machines (VMs).
Compute Engine (GCE) is the first suitable choice for running legacy, large, or complex applications, especially when those applications require full control of the operating system, environment, and underlying software configurations. It’s like the natural place to start with your big monolithic application in the cloud.
You could say that with this model, you are hosted in the cloud but you’re not taking advantage of some of its key benefits.
It’s also the case when you have specific or custom requirements or dependencies that are difficult to fit into a managed service or containerized environment. Some legacy applications require very specific (old, not already supported ) versions of software that may not be changed.
Key points:
Predictable performance. Compute Engine can provide consistent performance characteristics, but it needs to be predictable and reliable.
Versatile use cases. There are a lot of suitable use cases: From hosting websites and running backend services to performing complex analytics and running high-performance computing workloads.
Manual scaling. You can leverage all the integrations with other services, security, VPCs… You have full flexibility to create custom configurations, OS, storage, etc. Similar to EC2 AWS Cloud. Full control over a virtual machine.
Vertically (by increasing machine resources) It requires stopping and restarting the instance
Horizontally (by adding more VMs.
You can create Managed Instance Groups which can automate some aspects of horizontal scaling or even employ additional tools like Terraform, Cloud Deployment Manager, Ansible… But it requires time investment and expertise.
Google Kubernetes Engine (GKE)
A cluster of VMS that runs containers. It’s more complex than running VMs. Applications need to be more “cloud native”. This is where it gets serious hahaha…
Let’s say getting into GKE is a good idea when you have a global large user base across multiple locations and requirements for low latency, traffic peaks, automatic rollouts, automatic adjustment of the number of nodes and pods without manual intervention…
GKE Is best suited for applications that are split into containers and microservices that can scale independently. Good for running diverse workloads, including large, complex jobs.
GKE itself is a managed Kubernetes service, but it offers two modes:
a) Standard mode: This is the traditional GKE offering, where Google manages the control plane, but you have more control over the node pools and some cluster operations.
b) Autopilot mode: This is a more fully managed option where Google handles most of the cluster management tasks, including node provisioning and scaling.
GKE and AWS EKS provide high control over containerized applications, as they both manage Kubernetes clusters. You handle the orchestration, scaling, and distribution of workloads across multiple nodes.
And then we have another option: Self-managed Kubernetes on Compute Engine:
You can manage to create your own Kubernetes cluster using Google Compute Engine VMs. This gives you full control but requires more expertise and management overhead.
For most users, GKE (either Standard or Autopilot) provides a good balance of control and managed services. The self-managed option on Compute Engine is typically chosen by organizations with specific requirements or those who need complete control over their Kubernetes environment.
Running a self-managed Kubernetes cluster on Compute Engine is generally more complex than using a fully managed Kubernetes service like Google Kubernetes Engine (GKE).
GKE. When to Use:
Control: High control over containerized applications. You manage the Kubernetes clusters, which can automatically scale and distribute workloads across multiple nodes optimizing resources.
Use Cases: Best for microservices architectures with auto-scaling and cost-efficiency.
Restrictions: You still need to manage the Kubernetes cluster, though some of the infrastructure management is abstracted. Operational complexity is lower than Compute Engine BUT introduces its complexities related to Kubernetes management.
GKE Key points:
Stateless containerized applications:
This allows for easy deployment, scaling, and management.
GKE is ideal for stateless applications that don't require persistent local storage: Web servers, microservices, and API backends.
While GKE works best with stateless apps, stateful applications can also be deployed if designed properly. These stateful applications should use persistent volumes and be designed to handle pod rescheduling.
Applications designed for scalability and availability:
GKE excels at horizontal scaling, so applications that can scale out by adding more instances work well.
Services that can handle variable loads benefit from GKE's autoscaling capabilities.
Cloud-native applications:
Services that leverage cloud-native patterns and technologies (like service mesh, circuit breaker, CQRS, ...) align well with GKE's features.
GKE's ability to automatically scale resources makes it ideal for applications with fluctuating demands.
Multi-zone and regional clusters.
Managed services (the provider takes care)
Managed services are cloud solutions where the provider handles most of the operational tasks, including infrastructure management, maintenance, scaling, and security. Users can focus on their application and business logic.
Opt for managed services when you want to minimize operational overhead and focus on application development. They are ideal for projects where rapid deployment, ease of use, and automatic scaling are crucial. They work well for smaller applications, microservices, and serverless architectures.
However, the irony is that some users start with these services and later question whether they are truly getting the best deal.
Cloud Run
Serverless containers approach
In my opinion, regarding this service, It's important to note that Cloud Run is primarily designed for stateless applications. The platform automatically scales containers up and down, including to zero, which means local storage is not persistent between instances. For applications requiring significant persistent storage, you may need to carefully consider the architecture and choose the appropriate storage solution based on your specific needs and usage patterns.
Key features:
Serverless Containers: Cloud Run allows you to run stateless, HTTP-triggered containers in a serverless environment.
Scalability: It automatically scales up or down based on demand, even scaling down to zero when there are no requests, which optimizes resource usage and cost.
Ease of Use: Cloud Run abstracts away infrastructure management, enabling developers to focus on application development.
Cost Efficiency: You only pay for the resources used during request processing, billed to the nearest 100 milliseconds.
Integration: Seamlessly integrates with other Google Cloud Platform services, such as Cloud Pub/Sub, Cloud Storage, and Cloud SQL.
Limitations:
Stateless Workloads: Cloud Run is best suited for stateless applications, APIs, or web services. It is not ideal for long-running processes, as the default request timeout is 15 minutes, extendable to a maximum of 60 minutes
HTTP-Triggered: It primarily supports HTTP-triggered workloads, which may not be suitable for all types of applications
Cold Starts: Instances can experience cold starts if there are no idle instances to handle incoming requests, which might introduce latency
Watch this if your application requires low-latency responses
Overall, Cloud Run is a powerful solution for deploying containerized applications without the overhead of managing infrastructure, making it ideal for developers looking to leverage serverless computing for scalable, stateless applications.
Cloud Functions (fully managed)
Serverless functions: short-live, stateless, event-driven. Consider the execution limit and cold starts.
Control: Minimal control. Cloud Functions is a serverless platform where you deploy functions without worrying about the underlying infrastructure.
Use Cases: Best for lightweight, event-driven functions that run for short durations, such as processing file uploads, responding to HTTP requests, or triggering actions from other Google Cloud services.
Restrictions: Functions have a maximum execution time of 9 minutes, making them unsuitable for long-running or resource-intensive jobs. Also, limited to specific triggers (HTTP, Pub/Sub, etc.) and is generally best for simpler tasks.
Cloud functions are billed by execution milliseconds. So I believe this service may be a good option for unpredictable, intermittent workloads, BUT you need to watch the number of invocations per month or the total amount of running hours. There is a limit where you need to optimize costs and this option may be expensive
Summary
When choosing between cloud computing services, the level of control you have over the infrastructure often comes with trade-offs in terms of complexity, flexibility, and the ability to run different types of workloads and restrictions.
So if your use case is a short simple task or just a rapid deployment, you may choose Cloud Functions. If you want to run containerized applications without the burden of infrastructure management, you can pick up Cloud Run. Eventually, for very large or highly customized workloads, you might end up using Kubernetes (GKE, EKS) or even raw virtual machines (Compute Engine, AWS EC2), where you have full control but also bear the full burden of managing the environment.
The need to dive into the details of Kubernetes, managing clusters, or even dealing with networking and security configurations might seem counterintuitive.
After all, cloud computing was supposed to simplify things. But this complexity arises because as applications grow, the need for customization, optimization, and control also increases. At scale, even small inefficiencies can lead to significant costs, so having that granular control becomes crucial.

