
On paper my CV looks like it belongs to two people. One of them wrote a master's thesis on tensor decompositions for big data. The other has spent more than ten years in production C#, .NET and SQL Server, lately on exam platforms where tens of thousands of students arrive in the same minute. I have never experienced these as two careers. The habits I picked up in research are the ones I use most when I design or review a backend, and the backend work keeps changing how I read the math.
This note is about that overlap. It is more opinion than tutorial.
The short version of the timeline
- 2011 to 2015: B.Sc. in Applied Mathematics at Urmia University.
- 2016 to 2019: M.Sc. in Computer Science at Tarbiat Modares University. My thesis, "Big Data Learning with Tensor Representation", supervised by Dr. Mansoor Rezghi, introduced tc-SVD. I was a teaching assistant for Advanced Machine Learning and Data Mining in 2018 and again from 2020 to 2021.
- 2016 to 2018: .NET developer at Withem, a private social network for actors.
- 2019: at OmidanHozoor I rebuilt React and React Native apps and built versioned REST APIs documented with Swagger.
- 2020 to 2021: as a freelancer for Refah Bank's exchange house I built a back-office system that replaced spreadsheet-based FX remittance accounting, with the focus on reliability, transaction integrity and financial data consistency.
- 2021 to 2023: at Gozine2, first full-stack, then senior backend. I redesigned the reporting system to reduce database load, introduced Serilog structured logging, designed and deployed the Redis Sentinel setup that carried 45,000 to 70,000 concurrent users at exam peaks, and founded and led a four-person data science team.
- Since October 2023: senior backend engineer at NovaTech, where I architected an IRT-based adaptive testing platform serving about 89,000 students, lead .NET 6/8 microservices development and mentor five or more developers.
- 2024: a remote contract with Noraco, automating a PDF-to-LaTeX pipeline with LLM tagging for more than 5,000 questions.
Here are the four research habits that carried over, roughly in the order they changed how I work.
1. Respect the shape of the data
My thesis started from a complaint: the standard recipe turns an image or a video into one long vector before learning anything, and in doing so throws away the structure that made the data meaningful. Neighbouring pixels end up far apart. A tensor keeps each dimension as its own mode, and the methods built on it can use that structure instead of rediscovering it.
Backend systems make the same mistake in different clothes. Everything goes into one wide table, or one JSON column, or one cache key holding a large object when every caller reads one field of it. The question I learned to ask in research translates directly: along which axes is this data actually accessed? Per student, per exam, per item, over time? Those are modes, and each one suggests a different home.
In the adaptive testing note, for example, three kinds of data sit next to each other with completely different shapes. Item parameters are small, read on every request and changed rarely, so they belong in an immutable in-process cache. A session's ability estimate is a short array that changes with every answer, so it belongs in Redis with a TTL. Responses are the permanent record and belong in SQL Server. Put all three in the same store with the same policy, and at least one of them will be wrong.
2. Update, don't recompute
A large part of the literature on decompositions at scale is about one thing: when new data arrives, can you update the factorization you already have instead of recomputing it from scratch? Recomputing is simple and correct, and it is exactly what stops scaling first.
In backend work this is the most useful single question I know. The ability estimate in an adaptive test is a good example: the posterior after an answer is the previous posterior times one likelihood curve, so the session never replays its history. Reporting is where the habit pays most often. Before writing a query that aggregates everything again, I ask what changed since the last run and whether I can update only that. Sometimes the answer is no, because the data is small enough or corrections are too frequent, and a full recompute on a schedule is fine. I only want it to be a decision someone made on purpose.
3. Measure honestly
Research teaches you, sometimes painfully, that a method which wins on every benchmark usually means the comparison was unfair. You compare against real baselines, on the same data, and you report where your method loses as clearly as where it wins.
Performance work needs exactly that discipline, and it is easy to skip. At Gozine2 I used Locust load tests to find bottlenecks before exam peaks, and the rules I follow come straight from the lab: measure before changing anything, change one thing at a time, keep the baseline, and look at percentiles rather than averages, because the average is where slow requests hide. Without a before-and-after measurement, an optimization is an opinion, sometimes a good one.
4. Read the math behind the tool
In research you learn not to trust a method until you have read what it assumes. In my thesis the key observation was exactly that kind of hidden assumption: the t-product treats the third dimension as if it wraps around, which is harmless for some data and quietly wrong for images.
Production tools hide assumptions too, and they tend to surface at the worst possible moment. Redis replication is asynchronous, so a failover can lose writes that were already acknowledged. Maximum-information item selection overuses the most discriminating items, because that is what the information function rewards. An LLM picks each token from a probability distribution; temperature 0 lowers variation but, in practice, does not make the output deterministic. None of these facts is obscure. They are in the documentation or the math, for anyone who reads it the way you read a paper: looking for the assumptions first.
How the two tracks feed each other
The clearest meeting point so far was at Gozine2, when I founded and led a four-person data science team working on ranking, scoring and recommendation algorithms. That was research-style work inside a product company, and its results had to run inside the same systems that faced exam peaks, which kept the work honest.
The NovaTech platform is the same meeting from the other side. Item response theory decides what the system must compute after every answer; engineering decides whether it can do that for a platform that serves about 89,000 students, at the moments when many of them show up together. At Noraco the meeting point was an LLM in a data pipeline, where years in machine learning classrooms made me skeptical in a useful way: a model can be completely confident and still wrong, which is why I count the review console as part of the pipeline itself.
Teaching fed into all of it. Being a teaching assistant for Advanced Machine Learning and Data Mining forced me to explain things precisely enough that someone else could use them, and that is most of what mentoring developers and setting review standards comes down to.
The influence runs the other way as well. Production taught me things research rarely rewards: operability, failure modes, logging that answers the question you will have at three in the morning, and the value of the boring solution your colleagues can maintain. When I read a paper now, I ask what it would cost to run and what happens when it fails. Those questions make me a slower reader and, I think, a better one.
Why I keep both
I don't think a backend engineer needs a mathematics degree. Most of the hard parts of this job are about people, deadlines and systems that fail in boring ways. But the habit of asking what shape the data has, what assumption a tool makes, and what a number actually measures has been worth more to me than any single framework, and I have not found a better way to keep that habit than to keep doing some research.
That is why this site has two tracks. The tensor guides continue the research side, starting from the ideas in my thesis. The Backend Notes are the other side, and you can find both on mahdimolavi.ir. The next note goes back to production work: structured logging with Serilog in ASP.NET Core.
This note is also available in Persian: read the Persian version.
