By Chirag Patil · · 5 min read
Architecting an Analytics Backend
This blog post details the architectural decisions and philosophies behind building a robust backend system for a startup, focusing on FastAPI, PostgreSQL, and advanced SQL techniques.
There’s a unique thrill that comes with joining a startup at the very beginning. For me, it was a call from a friend with a brilliant, simple idea: help local cafes not just survive, but thrive by understanding their customers better. The mission was clear, the passion was there, but the technology was a completely blank canvas. As the founding engineer, my job was to design and build the entire backend system—the engine that would eventually power their entire retention platform.
The challenge was twofold. I had to build something that could get us to market quickly, but I also had to make architectural decisions that wouldn't cripple us a year down the line. This is the story of how I approached that challenge, the key technologies I chose, and the philosophies behind them. It’s a look at the "why" behind the "what," a process I hope offers value to anyone starting a similar journey.
FastAPI
The first major architectural decision was the web framework. In a small, fast-moving team, your tools should be accelerators, not obstacles. I needed a framework that wouldn't fight me. After careful consideration, I chose FastAPI for a few very human reasons.
First, developer velocity. I knew I’d be the only backend developer for a while. I couldn't afford to spend weeks wrestling with complex configurations or writing boilerplate code. FastAPI’s simplicity and reliance on standard Python type hints meant I could build robust, production-ready endpoints in hours, not days.
Second, and perhaps most importantly, was its integrated data validation. FastAPI is built on Pydantic, which enforces data schemas at runtime. This was more than a convenience; it was a long-term bet on data quality. By defining the exact structure of the data I expected—a sale must have a float amount, a customer_id must be an integer—I was building a self-defending API. It guaranteed that no malformed data could pollute our database, saving me from countless future headaches and ensuring the analytics we provided were built on a foundation of truth.
Finally, I was thinking about the future team. FastAPI automatically generates interactive API documentation from the code itself. I wanted to build a system where our future frontend developer could immediately understand and experiment with every endpoint without having to constantly ask me for details. I was designing for collaboration from day one, trying to minimize the communication bottlenecks that can slow a small team down.
Our Database Choice
In an analytics company, the database isn't just storage; it's the most valuable asset. While the tech world was (and still is) buzzing with various NoSQL solutions, I made the deliberate, almost "boring" choice to use a traditional relational database: PostgreSQL.
My reasoning was simple: a cafe's business is built on concrete, structured relationships. There are customers, there are sales, and there are menu items. A sale is meaningless without the customer who made it. A relational model, with its enforcement of foreign keys and constraints, perfectly mirrors this reality. It makes it impossible to have a sale logged for a customer who doesn't exist.
This choice was about building for trust. Down the line, when the CEO or a cafe owner looks at a dashboard and asks, "Are you sure this revenue number is correct?" I wanted to be able to say "yes" with absolute confidence. That confidence doesn't come from fancy algorithms; it comes from the fundamental, structural integrity of your data store.
Powerful SQL Functions
Here’s the principle that guided most of my work: keep the computation as close to the data as possible. It would be easy to pull thousands of records from the database into the Python application and perform calculations there. It would also be incredibly inefficient and slow. The database is optimized for sifting through millions of rows of data; a Python script is not.
So, I leaned heavily on the power of SQL, pushing it far beyond simple SELECT statements.
I started with aggregations, the bread and butter of any dashboard. Functions like SUM(), AVG(), and COUNT(DISTINCT ...) were the building blocks for our core KPIs. But the real breakthroughs came from more advanced features.
I remember the day the product manager asked, "How can we identify customers who are at risk of churning?" The answer lay in window functions. This powerful SQL feature allowed me to perform calculations across a set of related rows. I could now ask the database, for every single purchase a customer made, "How many days has it been since their last purchase?" and get an answer for every row. This one query, executed lightning-fast within the database, gave us the core data to build a churn prediction model, a task that would have been a nightmare of nested loops in the application layer.
As our questions became more complex, I relied on Common Table Expressions (CTEs) to keep my sanity. I think of CTEs as the storytellers of a query. They allow you to break down a complex problem into a series of logical, readable steps. Instead of one giant, unreadable query, I could write a story: "First, let's find all the customers who signed up in May. Next, let's gather all the purchases only those customers made. Finally, let's calculate their average lifetime value." Each step was a named CTE, making the entire process clean, maintainable, and easy for anyone (including my future self) to understand.
Key Takeaways
Looking back, the backend we built was a testament to a few core beliefs: choose tools that empower the developer, build on a foundation of structural trust, and delegate work to the component best suited for the job. The code itself has evolved, but those founding principles remain. The greatest satisfaction comes not from writing a clever piece of code, but from building a system that works, that provides real value, and that sets a young company on the right path for growth.