In Java, everything is passed by value, including object references. When you pass an object x to a method, you are passing a copy of the reference to the object, not the actual object itself. This means:
1. If you modify the object via the reference (e.g., x.setName(“newName”);), the changes will affect the original object because both the original reference and the copied reference point to the same object in memory.
2. If you reassign the reference inside the method (e.g., x = y;), the reassignment only affects the copy of the reference. The original reference outside the method remains unchanged.
Scalability is the ability of a system to handle an increased workload without losing performance.
However, we can also look at scalability in terms of the scaling strategy.
Scalability is the system’s ability to handle an increased workload by repeatedly applying a cost-effective strategy. This means it can be difficult to scale a system beyond a certain point if the scaling strategy is not financially viable.
Three main bottlenecks to scalability are:
1 – Centralized components: This can become a single point of failure
2 – High Latency Components: These are components that perform time-consuming operations.
3 – Tight Coupling: Makes the components difficult to scale Therefore, to build a scalable system, we should follow the principles of statelessness, loose coupling, and asynchronous processing. Some common techniques for improving scalability are as follows:
- Load Balancing: Spread requests across multiple servers to prevent a single server from becoming a bottleneck.
- Caching: Store the most commonly request information in memory.
- Event-Driven Processing: Use an async processing approach to process long-running tasks.
- Sharding: Split a large dataset into smaller subsets called shards for horizontal scalability.
Generative AI and LLMs are fast becoming a game-changer in the business world. Everyone wants to learn more about it. The landscape covers the following points:
1 – What is GenAI?
2 – Foundational Models and LLMs
3 – “Attention is All You Need” and its impact
4 – GenAI vs Traditional AI
5 – How to train a foundation model?
6 – The GenAI Development Stack (LLMs, Frameworks, Programming Languages, etc.)
Below is a diagram showing the evolution of architecture and processes since the 1980s. Organizations can build and run scalable applications on public, private, and hybrid clouds using cloud native technologies. This means the applications are designed to leverage cloud features, so they are resilient to load and easy to scale. Cloud native includes 4 aspects:
1. Development process This has progressed from waterfall to agile to DevOps.
2. Application Architecture The architecture has gone from monolithic to microservices. Each service is designed to be small, adaptive to the limited resources in cloud containers.
3. Deployment & packaging The applications used to be deployed on physical servers. Then around 2000, the applications that were not sensitive to latency were usually deployed on virtual servers. With cloud native applications, they are packaged into docker images and deployed in containers.
4. Application infrastructure The applications are massively deployed on cloud infrastructure instead of self-hosted servers.
Choreography is like having a choreographer set all the rules. Then the dancers on stage (the microservices) interact according to them. Service choreography describes this exchange of messages and the rules by which the microservices interact.
Orchestration is different. The orchestrator acts as a center of authority. It is responsible for invoking and combining the services. It describes the interactions between all the participating services. It is just like a conductor leading the musicians in a musical symphony. The orchestration pattern also includes the transaction management among different services.
The benefits of orchestration:
1. Reliability – orchestration has built-in transaction management and error handling, while choreography is point-to-point communications and the fault tolerance scenarios are much more complicated.
2. Scalability – when adding a new service into orchestration, only the orchestrator needs to modify the interaction rules, while in choreography all the interacting services need to be modified.
Some limitations of orchestration:
1. Performance – all the services talk via a centralized orchestrator, so latency is higher than it is with choreography. Also, the throughput is bound to the capacity of the orchestrator.
2. Single point of failure – if the orchestrator goes down, no services can talk to each other. To mitigate this, the orchestrator must be highly available.
Real-world use case: Netflix Conductor is a microservice orchestrator and you can read more details on the orchestrator design.
Think of JWT like a movie ticket for your app. It proves who you are and what you're allowed to do.
Here's how it works:
- 1. Login: You log in to an app.
- 2. JWT Creation: The server creates a token with your info (like user ID) and signs it with a secret.
- 3. Token Use: The token is sent to your app, and every time you make a request, it’s sent back to prove it’s you.
- 4. Server Verifies: The server checks the token's signature to confirm it hasn’t been tampered with.
Why use it?
JWT is self-contained, secure, and doesn’t require the server to store session data. Just make sure to avoid sensitive info in the token and always use HTTPS!