I left my first software engineering job for a strange reason.
Things were going well.
Management trusted me. I had taken ownership of a difficult freight-management module, improved the user experience, and built a strong relationship with the client. I had even started my career with a senior title, despite having none of the experience normally associated with it.
I tell that strange beginning in I Started as a Senior Engineer by Accident.
But the important part for this story is what happened next. I knew there was a gap between delivering software and designing it well.
I could make things work. I did not yet understand how to build systems that remained understandable when requirements changed, teams grew, or the original developer left.
I wanted to learn the better way.
A company that felt like a university
By then, I knew some of the stronger software companies in Bangladesh, including companies many local engineers considered dream workplaces.
The next company I joined offered me lower pay. I accepted without much concern. At that point, salary was not the main thing I was optimizing for. I wanted to work around engineers who could challenge me.
I joined SELISE Rockin’ Software as a frontend developer.
Frontend development was never my favourite area. I was good at it, but I have always approached work practically. If the company or team needs something, I can learn it and do it properly. I do not necessarily need to love every technology involved.
SELISE was another unusual company, but this time in a good way.
On my second day, my manager took me downstairs to play table tennis. Instead of playing, he gave me a deadline. I had one week to prepare.
He told me to watch as many tutorials as I could and learn what I needed for the role. I did not spend the week jumping between random videos. I bought two complete Udemy courses, one by Maximilian Schwarzmüller and another by Andrei Neagoie.
They were amazing. The courses went into detail about almost everything I needed. I watched them almost like television series, although I also stopped to practise and build things along the way.
For one full week, learning was my job.
Then I received my first task. I completed it well. The second task went well too, and then the third.
Before long, I was given the autonomy to choose tasks, plan the work, and estimate deadlines.
That trust felt different from the responsibility I had received in my first company. At my first job, responsibility came because there was nobody else. At SELISE, responsibility grew as I proved I could handle it.
That difference mattered more than I initially understood. Being given responsibility can feel like growth, especially early in a career. Sometimes it is. But responsibility without feedback can also teach you to repeat the same mistakes with greater confidence.
The environment felt more like a university than a traditional office. The main expectation was simple: get the work done and take responsibility for it.
The senior engineers were approachable. We played sports together, went on trips, and spent time together outside work. Nobody seemed particularly interested in what time I entered the office or what time I left. They cared about whether I was dependable and whether the work was completed properly.
In my first company, I had been forced to appear senior. At SELISE, I was finally allowed to be a learner.
Discovering how much I did not know
I was confident about my work when I joined. Then I met competitive programmers.
There were many of them in the company, and they thought differently from me. They could break down problems quickly and find solutions that were cleaner and more efficient than mine.
That affected me. I did not necessarily want to become a competitive programmer, but I wanted to become a better problem solver.
So I started solving LeetCode problems. My target was simple: one problem a day, usually the daily challenge. Some days I solved the problem. Other days I spent more time understanding why my approach was wrong.
At the same time, the conversations around me were changing how I understood software. People casually discussed architecture, problem solving, low-level design, high-level design, microservices, design patterns, and optimization.
These discussions were often unrelated to the task anyone was currently working on. People simply enjoyed talking about how software could be designed. I loved being around that.
Many of the questions I had been asking in my first job suddenly had names.
I had wondered how responsibilities should be divided. That was part of low-level design. I had wondered how large services should communicate and where system boundaries should exist. That was part of high-level design and architecture. I had worried that changing one feature might break several unrelated modules. Now I was learning about coupling, cohesion, contracts, and separation of concerns.
The concerns were not entirely new to me. The vocabulary, discipline, and experience around them were.
The framework team I wanted to join
One of the most interesting things about SELISE was that the company had its own frameworks.
There was a team building shared frontend and backend foundations. Other teams used those frameworks to deliver solutions for different clients. Around seven to ten teams could build on the same internal platform.
This meant faster delivery, more consistent applications, and shared solutions to common problems. Instead of every team independently deciding how authentication, forms, data access, and project structure should work, much of that foundation was already available.
To me, this was amazing. It looked like the kind of engineering I wanted to do.
I did not only want to build features inside one application. I wanted to build foundations that helped many teams create applications more consistently.
But I was still too junior to join that team. My immediate team believed in me, but joining the central framework team required proving myself to people outside it. That would take time.
Then the company began to change.
I heard that the CTO was moving to a new company to build a new architecture from scratch. Several people around me joined him, including my manager, his manager, and other colleagues I loved working with.
Deep down, I wanted to go too. I wanted the opportunity to work on a new architecture from the beginning, not only use decisions someone else had already made.
Then COVID arrived, and they left.
I was disappointed, but I was still working at a company many Bangladeshi developers considered a dream workplace. I continued learning and doing my job.
A few months later, my former manager called me. He first asked how I was doing. Then he explained that they needed someone to work on the frontend framework they were building. It was exactly the kind of shared foundation I had wanted to work on at SELISE.
I did not negotiate. I immediately said yes.
Building the foundation
I spent roughly the next year working on the type of framework I had wanted to own.
The work exposed me to microservices, event-driven architecture, progressive web applications, shared frontend foundations, design discussions, and planning. There were always new challenges.
A decision inside the framework could affect every team building on top of it. That changed how I thought about seemingly small choices.
A shortcut inside one product might create a local problem. A shortcut inside a shared framework could create the same problem across many products.
The work forced me to think beyond whether my own feature worked. I had to think about consistency, migration, backward compatibility, developer experience, and what another engineer would understand without having me beside them.
More importantly, we were building a product for the local market. I could see people around me using it.
That felt different from delivering software for a distant client whose users I would never meet. The product existed in the same world I did. I could see how our decisions affected real people.
Unfortunately, the good period did not last.
The company ran out of funding, and almost the entire team was laid off. Only four or five people remained.
We all knew it was time to move again.
It was painful to leave the kind of work I had spent years trying to reach, but it also reminded me that good engineering does not protect a company from every business problem.
A well-designed product can still run out of money.
Maintainability was not about chasing architecture
I joined Cefalo and began working with House of Math, an education platform focused on mathematics.
House of Math was a startup, and the team had deliberately avoided chasing fashionable architectural choices. There was no attempt to use microservices simply because other companies were using them.
But that did not make the system simple. It had a large user base, a growing codebase, and a product that kept evolving.
I joined after many of the important architectural decisions had already been made. I started by improving parts of the frontend architecture and eventually moved into backend work as well.
I contributed to features across much of the platform before focusing more heavily on gamification.
Every feature brought a different challenge. Some needed to work across a large number of users. Others required product decisions that were as important as the technical implementation.
House of Math taught me another important lesson.
Maintainable software does not come from choosing a particular architecture.
Microservices can be maintainable or chaotic. A monolith can be maintainable or chaotic.
The architecture matters, but what matters more is whether the design fits the product, the team, and the problems they actually have.
A complicated architecture is not automatically a mature one. Sometimes the more senior decision is to avoid complexity that the product does not need.
I will probably write separately about some of the systems I built there, including features that handled data for millions of users. Those stories deserve more detail than this post can give them.
Looking for a new kind of complexity
After several years, I wanted another change.
I was becoming bored with staying in the same country and wanted to explore the global market.
Around that time, a friend joined Odoo and asked whether I was interested.
Odoo was one of the largest ERP software companies, and it offered exactly what I was looking for: a new industry, a new scale, a new city, and a different type of engineering challenge.
I joined Odoo in 2024.
By then, my understanding of software engineering had changed significantly.
I began my career believing that seniority meant taking responsibility and delivering difficult work. Those things still matter.
But I later learned that senior engineering also means understanding tradeoffs, creating clarity for other people, and building systems that can continue changing after the original developer is gone.
My first company taught me to take ownership. SELISE taught me how much the environment matters. Working on shared frameworks taught me how architectural decisions can multiply across teams. House of Math taught me that good architecture is contextual, not fashionable.
Each stage helped me design software that was easier to understand, maintain, and change.
Learning to build had given me confidence. Learning to design maintainable software gave that confidence boundaries.
It also created a new problem.
The more I learned about good design, the easier it became to see flaws in everything I built. At work, deadlines, users, and teammates helped me decide when the design was good enough.
In personal projects, those boundaries were missing.
That is where design sometimes stopped being engineering and started becoming avoidance.