
Software Engineer/Architect. I have experience in building ecommerce platforms, delivery services, and analytics dashboards.
Technologies I have used include, but are not limited to:
-Node.js Express, JavaScript, TypeScript, Rust, Python, C++, C, Flutter, Android
-Docker, Firebase FCM, AWS (SQS, S3, SNS), Kubernetes, Git, CI/CD
-PostgreSQL, MySQL, MongoDB, DynamoDB, Redis
-Routing services like OSRM and Google Maps
I have a strong passion for algorithms and a keen interest in crafting complex backend applications on a large scale. I am a professional with a Bachelor of Computer Science from Mumbai University, with a CGPI of 9.5/10.
Senior Software Engineer
DAZN Software Pvt. Ltd.Software Engineer
Techshack Pvt. Ltd.Full Stack Developer
E2E Research Services Pvt. Ltd.
MySQL

Git
REST API
Node.js

MongoDB

Slack

Javascript

PostgreSQL
Jira

Postman

Microsoft Teams

AWS Cloud

Google Maps

OSRM

Amazon DynamoDB

NodeJs

Express

Typescript

AWS SQS

SNS

Dynamodb
.png)
Docker

Kubernetes

Github Actions

Redis

Kibana

Confluence

Terraform

GitHub Actions
It is with great pleasure that I recommend Amogh Chavan for any back end development role. Amogh worked with us at Speedyy for 2 years, during which he consistently showcased his remarkable talent and speed in coding. His ability to swiftly grasp the ideas of our product managers and deliver on requirements was truly impressive.
One of Amogh's standout qualities was his seamless collaboration with our front end team, resulting in a cohesive and efficient workflow. His contributions were instrumental in the successful development and deployment of several key products, including food delivery, grocery delivery, pharmacy delivery, and pick-up and drop services.
Beyond his technical skills, Amogh's dedication and work ethic were exemplary. He consistently went above and beyond, often putting in extra hours to ensure project success, without hesitation. His commitment to excellence and willingness to go the extra mile made him an invaluable asset to our team.
In summary, Amogh Chavan is an exceptionally talented and diligent back end developer who would be a valuable addition to any team. I highly recommend him without reservation.
https://drive.google.com/file/d/1R0vWgOuRGEU0tohmLYZdR-KYyrY7S2aC/view
https://drive.google.com/file/d/1eLSqx-IbuCC-9E1uPfOqv7qk81BrRZPS/view?usp=drive_link
Will you help me understand more about your background? Okay. So, I am a software engineer. I build robust and scalable back-end systems. I have been working with Node.js for the last 4 years. My passion for Node.js started 4 years ago when I was in my graduation. Then I used to do freelancing work, then I joined an organization in Delhi, named D2E Research Services where I created few data analytics dashboards for them. It was a survey company, so they had a lot of data coming into their databases, and they needed a tool to visualize all that data. So I created a data analytics tool, which had a stack of React for the front end and Mules for the back end with a database as MongoDB. It had all sorts of operations like transpose, maybe all sorts of different forms of graphs, clubbing two questions using dynamic filters, and all sorts of that. Then I joined the organization Speedy, which is a product-based startup. Speedy is basically India's first super app, and it has all the e-commerce platforms in it, like Swiggy's, but you don't have to install 10 different apps. You just have to install one app, and you can access all those e-commerce platforms. Luckily, I was with Speedy from day one, so I had the opportunity to design the back-end distributed systems and did all sorts of database schemes and work on all the cool features. So I have a good understanding of how e-commerce platforms work, and we did well. We had around 1 lakh orders in 1 year. We had a lifetime of 30,000 users, and we had our own in-house logistic service. So this is a little bit about me.
What approach would you take to manage transactions in mergers interfacing with? What approach would you take to manage transactions in a Node.js application? So, we have to use the transaction object of Postgres. If that's the case, let's take an example. If it's a banking application and we want to update an entry of a deposit in two tables, then we need to create a transaction object and we need to pass that transaction object in the insert queries or update queries of two tables. In the end, we have to commit the transaction. With the help of a transaction, we can maintain that data is synchronized across all tables and does not get partially synchronized in case the system fails during a transaction process. So, I would basically in my Node.js application, I would create a database module where there would be a class called Database, and that class would provide a transaction generation function, which would generate a new transaction every time I call that function. So, each time I will get a new transaction object, I can pass on the transaction object to my custom model functions, and I can commit the transaction or roll back the transaction depending upon the business logic for that.
What would be the strategy for handling session management in a scalable node? Just APS. Okay. So, for session management, what we can do is, whenever the user logs in, we can store a session ID and generate it. We can store that session ID in a persistent database or a cache database like Redis. And whenever the user logs in to the application, we will check if there is already an active session or not. And if the session is active, then we will delete the previous session ID, and we will generate a new session ID. So, let's take an example. Suppose a user hits the login API, we'll generate a session ID and store that session ID in a database. We will add that session ID to a JWT payload and return that payload to the user. That user will use the JWT payload to access all the APIs. And in each API, the backend system will decode that JWT. It will check if that JWT contains the session ID. Is that session ID valid, and is that session ID currently in the database against that user? And if the session ID matches, then that user will be authorized; otherwise, we will return a 401. And by that, we can basically manage session IDs. So, basically, we can use JWT to store the session ID and a database to store the session ID. And we will generate the session ID every time a user logs in, so the session ID gets overwritten. So, by this week, we'll have a good session management system. We can also use cookies, but JWT is also an option, so we have both options.
In what ways can you utilize the observer design pattern in Node.js involving RabbitMQ? Observing old patterns in Node.js. Okay. So let's take an example. Suppose we're designing a backend system for a food delivery application. And we need to process all events in a single way. So suppose if a new order comes into the system, we need to inform the restaurant about the new order. We need to find a delivery partner for that order. We need to do all sorts of operations. We need to update multiple tables. We need to send push notifications to vendors and customers. We need to send an email to the customer regarding the payment method and the bill. We need to do all sorts of operations. If we do this in the API itself, it will be very bulky. There are chances that it could get partially completed and the system might fail. So in such scenarios, what we can do is we can push a message into RabbitMQ, and RabbitMQ will forward the message to different channels. And, yes, there will be different channels. Like the delivery partner will be listening to this channel, and there will be another restaurant channel. And once that message is pushed into the Rabbit queue, multiple entities will get that message. They will do processing with that message, and they will update the respective databases and do their respective operations. Using RabbitMQ, we don't have to do this in a common API. We can use the async way using queues, and it would be efficient. So the API would be fast. We would simply return 200 and tell the customer we have accepted your order, and we will process it at a later point.
When designing a RESTful API model, how would you ensure its versioning for future updates? Okay, so versioning APIs is very important. There are few versioning API versioning strategies. On top of my head, I can remember there is a URL versioning strategy, and we can also have a header parameter in the API. So, let's talk about the first way. What if you add the version in the API URL itself? So, if your URL is xyz.com/apis/placeorder, and suppose you want to create a new version of the place order, so the API will be xyz.com/versionone/placeorder. This is only one way, but the problem with this is that every time we need to change a version, we need to create a new route and a new controller. It might also be beneficial because we are separating the old route and the new route. However, there is also another way in which we can have the route as the same, and we can just simply pass the version in the headers of the API. So, the route will be always xyz.com/placeorder, and in the headers of the API, we'll pass a version key and value. And at the backend system controller level, we will switch depending on the header version value. So, this is one of the version strategies. These are the two ways. There is also a third way: sending the version into the query parameter. So, these are maybe three ways. There are also other ways, but these are widely used.
What caching strategies can be employed in order to enhance API performance? Okay, so to enhance API performance, caching is the last resort of improving performance, because maybe your database query is slow, or maybe your logic is slow. Okay? So caching should be used as the last stage of resort to improve the performance of APIs. And suppose if you want to use caching, then there are multiple caching databases like Redis and Memcached, in which we can cache the results. So, instead of hitting the database, we can hit the cache. Most tools, like databases, already have an inbuilt cache in them. Load balancers already have an inbuilt cache in them. So if a route is getting a request multiple times, or if a database is executing a query, and it's submitting the same output, these tools already have an inbuilt cache in them. But if you still want to build a custom cache that works for your custom logic, then you can use a cache like Redis. Let's take an example. Suppose we have a food delivery platform and we want to send the list of restaurants to a customer whenever they open the app. That list of restaurants can be up to 500 or 1,000. And we can't calculate for each customer on each API request if each of these 500 restaurants are open or not, or are they operational or not. So, we can precalculate this. We can precalculate all the restaurants' opening and closing times, and we can store that time in the cache itself. And whenever a customer opens the app and checks the list of nearby restaurants, we don't have to recalculate the opening and closing logic for each restaurant. We can just simply check the cache value for that restaurant. We can also use, like, suppose if there are two users who live in the same building. They live in the same building, and they are opening the app. So, in a long perspective, there might be a significant point of difference in a geographical perspective. But, in reality, they live in the same building. So, instead of recalculating the entire fetching of restaurants logic, we can just simply create a zone, a small zone, and we can cache all the restaurants for that particular zone, and we can store that result in it. So whenever a user who belongs to that zone gets the list of restaurants, it will get the cached result. So caching can be used in such a way that it would significantly improve the performance, and it will reduce the cost.
Creating a new session every time can be avoided by implementing a singleton database object. This will return a single session instance, which can be used throughout the process. Instead of creating and closing sessions every time, we can maintain that session until the process exits, and then close it. This will improve the performance of the query. So, let's implement a singleton database object. We can use a class to create a single instance of the database session. Here's an example: ```python class Database: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super(Database, cls).__new__(cls) cls._instance.session = Session() return cls._instance # Usage: db = Database() session = db.session ``` This way, we can use the same session instance throughout the process, instead of creating a new one every time. This will improve the performance of the query and reduce the overhead of creating and closing sessions.
Examine the rest API return in fast API and identify the critical aspects of security that is missing. So this is how you would correct this oversight. Okay. From FastAPI, input FastAPI. Have dot get slash user slash user ID. Assign function, different define, read user ID, user ID as an integer, return user ID, and return username. Okay. So what I can see is there is a we are taking a user ID, and we are reading that user ID someone. We are returning that user ID. So identify a critical aspect of the security that is missing. Okay. So I can't see the authentication done here. So, like, if I can just randomly hit this API with random numbers and I can maybe fetch random customer details so that would be not secure. So first of all, we need a authentication mechanism like JWT or session to authenticate the user, and we don't have to take the user ID itself. So whichever way we are selecting for authentication, the payload, the cookie, or the JWT token will be attached with the request, and we will fetch the user ID from that JWT payload or that cookie payload. And we will then get the, we will then get the user details and return to that user instead of taking a custom user ID. If this, so this is the only improvement, and the improvement is, don't take, say, user ID in the route. Use some authentication mechanism, decode that payload, get the user ID, get the user details, and return the user details. And in the user details also, you don't have to return the user ID itself. You can just return username and your, and user phone number, whichever is non sensitive
How would you refactor a Monolith Node.js application to a microservice architecture considering current rapid architecture considering current usage. Okay. What we can do is in our Monolith application, we will have different modules, like, for example, an order module, a payment module, and a cart module. What we can do is first consider current revenue usage. Yeah. What we can do is, if we want to separate out the code into different microservices, we have to group all the related code together, like, models, APIs, and business logic based on their relatedness. All the files related to orders should be in one folder, payment-related code in another. If it's already organized in this way, all we have to do is separate those folders and run them as separate microservices. And to communicate between these microservices, we can use RabbitMQ. For example, if an order service wants to communicate with a payment service, the order service can push a message into RabbitMQ, and the payment service can consume that message and perform the necessary operations. So, all the modules will run as individual microservices, and for communication between them, we can use RabbitMQ or RESTful APIs within a virtual private network. So, refactoring would totally depend on the current code structure. If there's a folder with all the controllers, it would be challenging because we'd have to extract specific controllers related to each module and their services. If the code is already grouped together, we'd just need to make a few modifications and run them as separate microservices.
We can leverage TypeScript features in a Node.js backend project to enhance quality and integrity by defining types for each and everything. We have to define interfaces for each and everything, so there would be no runtime bugs. Only developers know what kind of data is expected or what kind of data should be there in a particular entity, and with the help of TypeScript, we can catch a lot of bugs, like which we will not be able to catch in JavaScript. We can define interfaces for each entity, have type validation checks, and the compiler can really help in catching type errors. So, yeah, we can all enhance port quality and maintainability. We can use interfaces, enums, classes, access modifiers, and all sorts of types of features to help in maintaining good quality. Besides TypeScript, we can use other solid principles to maintain or have defined rules on how to write or what type of naming convention to follow. We can have all the custom win logics.
How do you manage load balancing and auto scaling enabled with this cloud environment for Node.js? Okay, so we can auto-scale and load balance by using the AWS load balancer. We can also set up auto scaling groups. We can use Kubernetes clusters for this, which allows us to define auto scaling policies and how much we want to scale up or down depending on the load. And we can configure the load balancer to point to these clusters. And by doing this, we can manage auto scaling and load balancing. If we are using AWS, it is easily configured. But if we are not using AWS, then we can also use something like PM2 and NGINX. So we can use a combination of NGINX and configure it to manage load balancing and auto scaling for our Node.js application.