It would be an understatement to say that your tech stack makes or breaks the project. Not only does a tech stack determine the kind of app that the team will be able to build in the end, but it also directly impacts the efficiency with which the developers build it. Thus, it was imperative for the core team at FamPay to curate an effective yet dynamic tech stack.
Hello there, I am Pratik, a Backend Engineer at FamPay. I, along with the tech team, work on building the FamPay App for Gen Zs, such that they have a smooth, safe and spectacular experience. At the end of the day, we are problem solvers bringing forth the best solutions. And this, the Tech Stack, is at the foundation of all these solutions.
When the Founding team started working on building FamPay, the core team had experience in building backend with Django and Android app. We choose what we’re most comfortable with and knew it’s a scalable framework as it was used by Instagram (till ~2005), Pinterest, Disqus, Creative Commons.
Python - Most of the backend code is in python, Python's design philosophy emphasizes code readability with its notable use of significant indentation. Additionally, we use static code checking tools like flake8, black, isort to have consistent patterns. Now you can even code in notepad and still, that won’t break PEP8 guidelines xD.
Java - Mostly used by Android App, Java is a High Level, class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible.
Kotlin - Kotlin is a cross-platform, statically typed, general-purpose programming language with type inference.
Swift - Swift is a general-purpose, multi-paradigm, compiled programming language developed by Apple Inc. and the open-source community.
GoLang - Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. We use gokit here as Go kit fills in the gaps left by the standard library, and makes Go a first-class language for writing micro-services in any organization. To avoid writing lots of boilerplate code we use truss to make life a bit easier.
We are using Next.js deployed on EC2 (pm2 and Nginx) to power our frontend. You don't need to take care of bundling and get server-side rendering for free with code splitting and other features free. We're using PM2 as a process management tool. It automatically restarts services if they fail.
The FamPay android app is a native application built using Java/Kotlin and modern android frameworks. We use Retrofit + RxJava as our network framework. Since the app is ever growing and we need to test various new features rapidly, we have implemented some good solutions like changing servers on the fly within the app itself, or having a live log of all api calls using Chucker. With more than 2 million downloads, we had to make the app air tight in terms of payment security and also think of redundancies if something goes wrong.
iOS app is built on Swift/SwiftUI/Combine. We have ported some views from UIKit to SwiftUI. Since the app is ever growing and we need to test various new features rapidly, we have implemented some good solutions like changing servers on the fly within the app itself.
🧶 Web Apps / PWA
PWA is the primary web view build using HTML, CSS, JS with React JS Library which has multiple routes pointing multiple sections in the app like QNA, Rewards, Merchandise Checkout, IPL, etc. Build for rapid development and deployment on the fly, using the flexibility to run on both Android and iOS as a web view inside and the ability to update like a website, it greatly increases gamification speed of Fampay.
🗿 Django + Django Rest Framework
All backend parts are written in Python using Django and DRF. Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. It takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. To create REST APIs for the frontend we use DRF which makes it easy to create complex JSON objects.
Celery is a simple, flexible, and reliable distributed system to process vast amounts of messages while providing operations with the tools required to maintain such a system. It’s a task queue with a focus on real-time processing, while also supporting task scheduling. Celery workers get spawned via supervisord and they are using the eventlet worker pool for better concurrency.
We have highly relational data so choosing RDBMS was an obvious choice, Django has really good ORM support for Postgres as well. We heavily rely on its transactional properties. We are using PostgreSQL to store most of the data. It's deployed via AWS RDS - Postgres managed service.
You may have heard of it as the key-value in-memory database but it’s the Swiss Army Knife of NoSQL databases. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster. We use AWS ElastiCache to run Redis in cluster mode.
Many Open Source services we use requires MySQL as the database engine. This is also deployed using AWS RDS.
Segment collects events from your web & mobile apps and provides a complete data toolkit to every team in our company. It's the single source of truth for all app events.
Metabase is the fastest, easiest way to share data and analytics inside your company. We can connect many DB sources and it creates beautiful graphs for us. It makes it easy for a non-technical persona to ask questions about data. Using its alert feature we get notified if something is wrong with the data or application. Like successful transactions rate or any failure with external services.
MixPanel is a great product analytics tool to understand user behaviors, segment integration with mixpanel pushes data there.
PostHog provides analytics with auto-capture, session recordings, feature flags, heatmaps, and more. In a single product, you can host yourself (open source).
Retool is another great alternative to Metabase, We use this for specific features that are not available in metabase. We can set up a webhook here which helps in automation.
WebEngage helps us craft contextual and personalized campaigns to engage our users through Push Notifications, In-app Messages, SMS, Web Push, Emails, WhatsApp, Facebook.
n8n is a fair-code licensed extendable workflow automation tool, you can automate all kinds of the mundane processes using this as we live in API world you can connect pretty much anything. For example checking the CoWin website if a vaccine slot is available and if it is then notify you via slack, email, SMS, etc.
Sentry can help you fix that nasty bug that comes once in blue moon. Its application monitoring platform helps every developer diagnose, fix, and optimise the performance of their code. We are using self-hosted sentry on a large EC2 instance but you can check out their SAAS version as well.
👑 Elastic Search
ElasticSearch is a distributed, free and open search and analytics engine for all types of data, including textual, numerical, geospatial, structured, and unstructured. We push our Nginx and some external API call logs here. This is also self-hosted on EC2 by one of our interns. Yes, you read that correctly.
Kibana is a data visualization and management tool for Elasticsearch that provides real-time histograms, line graphs, pie charts, and maps. This goes hand in hand with elastic search 🤷 .
Fluentd is an open-source data collector for a unified logging layer. Fluentd allows you to unify data collection and consumption for better use and understanding of data. Instead of using Logstash, we opted for this as fluentd provides a better queuing mechanism and lower memory footprint other than that there are more plugins available for fluend.
NewRelic provides detailed insights on how your application running in production. You can visualize, analyze, and optimize our entire software stack from One place,
💇🏼♀️ GitLab CI
GitLab CI helps us integrating static code analysis tools and the Django test suite. We use black, isort, flack8 for static code analysis, so we don't need to comment about line limits, import order, or code formatting. Anyone can use any editor and in the end, everyone's code will look the same. Same for the GoLang microservice.
Docker takes away repetitive, mundane configuration tasks and is used throughout the development lifecycle for fast, easy, and portable application development. Most of codebase is containerised so it can run anywhere.
🚟 AWS ECR
Amazon Elastic Container Registry (ECR) is a fully managed container registry that makes it easy to store, manage, share, and deploy our container images and artifacts anywhere. As we're using docker we needed a place to store private images so what could be better than ECR which tightly integrates with other AWS services.
🪃 Amazon Elastic Beanstalk
AWS Elastic Beanstalk is an easy-to-use service for deploying and scaling web applications and services developed with Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker on familiar servers such as Apache, Nginx, Passenger, and IIS. All of our core services are containerised and deployed using Beanstalk.
Nginx is a high-performance web server that can also be used as a reverse proxy, load balancer, mail proxy, and HTTP cache. We mainly use it as a reverse proxy in front of open source projects, next server, python WSGI server. It handles SSL and sending responses to the clients.
Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork worker model. We observed that most of our traffic is IO bound so we changed its worker pool to gevent and monkey patched psycopg.
Traefik is a leading modern reverse proxy and load balancer that makes deploying micro-services easy. This helps us in setting up development environment. We follow git flow model so each feature branch should be tested independently by dev and QA team. It routes to different django servers based on CNAME.
Pulumi helps adopt infrastructure as code automation, combined with tried and true software engineering practices. One of the projects we are working on is to create a data pipeline and data warehouse. We are leveraging this to create and destroy AWS infrastructure. We recommend using TypeScript even though it supports Python and GoLang.
Hey is a tiny program that sends some load to a web application. Gives a nice latency distribution summary.
As you might have expected we are full-on AWS shop. Everything is deployed on AWS.
- EC2 - The basic building block of cloud computing.
- S3 - All of the assets required for the app to function.
- RDS - All of the user data. We have postgres, mysql instances with read-replica in private VPC.
- ElastiCache - Redis cluster with read-replicas for DB cache and rate-limiting.
- Lambda - External services integration.
- CloudFront - CDN for Application assets
- SNS - As part of service where Lambda (Producer) → SQS → SNS → Lambda (Consumer)
- SES - Simple Email Service used in Listmonk, Metabase, etc.. wherever we needed SMTP creds.
- API Gateway - Managing REST endpoints for external services
- SQS - Bridge between multiple services like Lambda functions.
- Route53 - Domain management and DNS based load balancing for db replica group.
- Athena - To query over Nginx logs
- CloudWatch - For monitoring all the infrastructure and alerts
- Firebase Remote config - Dynamically changing user flow and some dynamic values.
- Firebase Realtime Database - For Dynamic information where realtime sync is required.
- Firebase Dynamic Links - URL shortening.
- AWS Beanstalk - Deploying and scaling containerised apps.
- Chatbot - To receive infra alerts from cloudwatch on slack.
- IAM - To manage access policies.
As we use beanstalk to deploy a new version of the app all we need to do is create an image, push it to ECR, and refresh the beanstalk stack. We have developed shell scripts to do this in one go. Some independent application where we don't need auto-scaling, It's just simply doing ssh and doing your thing. There is the scope of lots of improvement like using terraform + terragrunt or pulumi to manage the infra and granular IAM policies.
Mailcow is a free, open source software project. A Mailcow server is a collection of Docker containers running different mail server applications This is the internal mail server for specific needs.
ListMonk is a self-hosted newsletter & mailing list manager. We use this for marketing and informational purposes.
A reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain, or group. OAuth2 proxy adds an authentication layer in between for projects like ListMonk and N8N
There are some key takeaways that the core team has realized through the journey:
- Choose a tech stack that you are most comfortable with.
- Picking the right tool for the right job is equally important.
- If you are facing a problem there is a good chance that an open-source solution exists for it.
- Go with the solution that works now and easily modifiable when required. We like to keep things simple.
- Automate business processes and repeating workflows.
- Consult with an expert when in doubt.
Keeping these things in mind will help you lay a solid and thoughtful foundation when you begin developing a project. It only makes things easier if critical thinking and decision-making have been done beforehand when choosing from the plethora of options available. However, in the end, experimentation and dynamism is key to arranging your tech stack.
Found this article interesting and want to share your insights? Drop in an email at firstname.lastname@example.org!