Hi, I'm Enes Efe Tokta.
In this article, I don't want to document FinTrack as a technical manual. Instead, I want to share the decisions I made, the challenges I faced, and the engineering mindset I developed while building this project.
This is Not a Step-by-Step Guide
You can find the technical implementation details in the GitHub repository. The purpose of this article is to explain how my way of thinking evolved while designing and building a backend system from scratch.
From Game Development to Web Backend
For nearly four years, I primarily worked with Unity and game development. During that time, my first interaction with a backend API sending requests from Unity unexpectedly sparked my interest in the web side of software development.
Because I already had a strong C# background, transitioning to ASP.NET Core felt natural. However, my first experience with it was far from smooth. I struggled not because the framework was complex, but because I hadn't yet understood the philosophy behind the .NET ecosystem.
Once I started learning how .NET approaches architecture, responsibility separation, and long-term maintainability, ASP.NET Core began to make sense. At that point, I realized something important:
"The way I think about problems aligns well with backend development."
That realization led me to focus fully on web backend engineering.
Why a Financial System?
The idea for FinTrack didn't come out of nowhere. While researching how to improve as a .NET developer, I came across a recommendation on Reddit:
"If you really want to become good at .NET, build a financial system."
That advice resonated with me. Financial systems:
- Contain complex business rules
- Strongly enforce object-oriented design principles
- Require data integrity, security, and consistency
- Closely resemble real-world enterprise software
In other words, they are excellent learning tools not just technically, but from a software engineering perspective. That's why I decided to build FinTrack as a financial tracking system.
Architectural Uncertainty and Planning
Before writing any code, my biggest challenge was choosing the right architecture. Since ASP.NET Core is commonly used with MVC, I decided to adopt it and learn it properly rather than cutting corners.
However, I quickly realized that a financial system isn't just about writing controllers and models—it requires careful planning.
The Planning Phase
I stepped away from the keyboard and started working with pen and paper:
- Designing classes
- Defining relationships
- Mapping business flows
Because I planned to use PostgreSQL, I also needed a solid database schema early on.
Throughout this process, I repeatedly asked myself:
"If I were the user, what would I expect from this system?"
For example, separating the concepts of Account and Budget took days
of thought. At first, they felt interchangeable. Today, that distinction feels obvious but only
because I wrestled with it early in the design phase.
Infrastructure Reality: Learning Docker
At this stage, I decided to introduce Docker into the project. I containerized both the web application and the database.
Lesson Learned
Software is not just code it's a lifecycle.
How an application starts, runs, scales, and is maintained is part of development. Once I understood Docker's purpose and mental model, the rest of the infrastructure decisions became much clearer.
Data Layer Decisions: Choosing EF Core
Initially, I handled database operations using raw SQL queries. Later, I explored ORMs and narrowed my options to:
- Dapper - Performance and simplicity
- Entity Framework Core - LINQ integration, migrations, database abstraction
Engineering Decision
Since FinTrack was not targeting massive scale, I accepted EF Core's performance trade-offs in exchange for development speed and maintainability.
This was a deliberate engineering decision not a default choice.
AI Integration: Idealism Meets Reality
As AI-driven features became increasingly popular, I wanted to integrate an AI-powered analysis component into FinTrack.
I initially experimented with Semantic Kernel, but its tight coupling with OpenAI made integration with Google Gemini difficult. After nearly five days of experimentation, I reached an important conclusion:
Critical Realization
Forcing a technology into a project rarely leads to good design.
Instead of pushing further, I restructured the system. I designed a separate Python-based FastAPI service responsible for AI interactions.
The flow became:
- ASP.NET Core → FastAPI
- FastAPI → LLM
- Response → ASP.NET Core
Due to API limits and cost considerations, I later switched to a local LLM setup using Docker with Ollama and Mistral 7B. This experience taught me the importance of dependency control and architectural flexibility.
Discovering SaaS and Payment Systems
While developing FinTrack, I encountered the concept of SaaS (Software as a Service). Initially, I thought SaaS simply meant subscriptions. Over time, I realized it represents a product-oriented mindset, not just a billing model.
Motivated by this insight, I implemented a membership and subscription system.
Because global payment solutions like PayPal are not fully available in Turkey, and local POS providers impose strict data constraints, I chose Stripe for integration. My goal was not monetization it was hands-on experience with a real-world payment infrastructure.
During this process, I implemented:
- Plan-based subscriptions
- Authorization tiers
- Stripe webhook handling
Since Stripe requires a public domain, I used ngrok instead of purchasing a domain,
exposing my local environment temporarily. This decision was purely learning-driven.
A Conceptual Experiment: Secure Debt System
To differentiate FinTrack conceptually, I designed a Secure Debt System as a thought experiment.
This system included debt offers, approvals, video confirmation, encryption, and one-time access keys. Legal considerations were intentionally excluded it was designed purely as a system design exercise.
Security Learning
This feature significantly improved my understanding of encryption, access control, and data security.
Operational Experience
Beyond core functionality, I also experimented with:
- CI/CD using GitHub Actions
- Secret scanning and security best practices
- Monitoring with Prometheus and Grafana
- Automated database backups
None of these were strictly required—but they helped me build a system that resembles real-world production environments.
Final Thoughts
Project Summary
FinTrack was the result of roughly five months of focused development.
It didn't just teach me new technologies it taught me how to make better decisions.
This project didn't make me a financial expert, but it did make me a more thoughtful backend engineer.
Key Lessons
- Plan before coding - Architecture decisions made early save time later
- Understand the philosophy - Frameworks make sense when you understand their principles
- Don't force technologies - Flexible design allows better solutions
- Think like a user - User perspective drives better design decisions
- Embrace the lifecycle - Development includes deployment, monitoring, and maintenance
- Learn by doing - Real projects teach more than tutorials
You can explore the code on my GitHub profile.