Reflecting on 2024: Lessons Learned and Growth in 2025 | Mind Spills by Admir Saheta

Reflecting on 2024: Lessons Learned and Growth in 2025

Reflecting on a Year of Growth, Challenges, and Transformation

As the dawn of 2025 unfolds, it’s time for a quick detour into reflection. 2024 was a rollercoaster of growth, challenges, and unexpected plot twists. For all the bugs and merges we faced, it was a year that pushed our limits and taught us to be more agile, creative, and resilient. As we step into the new year, let’s unpack the lessons learned that will continue shaping our code, projects, and lives.

The “Reset” Period: A Fresh Start for the Year

The first few days of 2025 are always my “reset” period: a time to refresh the codebase of my thoughts, reflect on what worked, and reboot where I missed the mark. And, as tradition goes, I kick it off with a fresh portfolio redesign and—of course—a new blog post. But this year feels different. It’s not just about the design changes—it’s about embracing simplicity and ensuring that every line of code contributes to something meaningful.

As many of you know, I’m a big advocate for open-source projects and collaboration within the community. Looking back, my website’s journey has been quite the ride. My first iteration in 2022 was built with React, following the protocol-oriented paradigm and using class components (which, I’ll admit, still holds a special place in my heart). Fast forward to last year, when I embraced Next.js after server components stabilized. This year, I wanted to streamline things—make it lighter, more content-focused. For me, simplicity is key, and a clean UI/UX based on a thoughtful color scheme and a solid font choice really hits the mark.

But the real change came when I decided to start a blog directly on my website instead of linking to Medium. That’s when I remembered Astro, and let me tell you—Astro is absolutely fantastic. Picture this: all your JavaScript is deferred, and hydration only happens on “islands.” It’s like a backend developer’s dream come true for frontend development, where loosely coupled microservices meet elegant UI. I couldn’t be more impressed.

A Shocking Career Twist: From Mobile Development to Microservices Mayhem

Looking back at the start of 2024, I can confidently say I’ve evolved into a completely different developer. In fact, I’d call this phase a tragic-comedic twist in my career. You see, I used to be deeply immersed in mobile development—React Native, Swift, Kotlin—you name it. I had a soft spot for the Apple ecosystem; Swift, in particular, always felt like more than just a programming language. It felt like using a finely crafted Apple product, each line of code designed with the same elegance and care you’d expect from an actual device.

But then, I made a 180. I dove into a project with an event-driven microservice architecture and a sprawling web application built on a distributed system. The tech stack? Well, let’s just say it was a little bit of everything. It was like jumping into the deep end of the tech pool, and let me tell you, I was scared sh#tless.

Microservices Chaos: The 27-Service Nightmare

Having worked with Apache Kafka and other brokers in the past, I felt relatively confident managing the architecture. But, oh boy, imagine a nightmare. I found myself dealing with 27 microservices—most of them built in PHP/Laravel and NestJS (which, by the way, I have a ton of love for). You’d think the decision to go with so many microservices was made to keep the system loosely coupled, right? Wrong. In reality, it was tightly coupled, distributed across different language stacks, varying versions, conflicting design patterns, and completely different software engineering paradigms. And to top it off, there were multiple teams working on this chaos.

Now, while PHP isn’t exactly my favorite language, I do love a good challenge. Plus, NestJS was already in my wheelhouse, so I was like, “Alright, I’ve got this.” But then came the real curveballs: microservices written in Lua and Clojure, and don’t even get me started on the nightmare that was the module-federation frontend. Picture this: a mishmash of Next.js, CRA, Storybook, and—hold your breath—just a few traces of jQuery sprinkled in. It felt like opening a box of tech spaghetti, where everything is connected but nothing makes sense. But hey, challenges are what make the adventure worthwhile, right?

The Cost of Chaos: The Debezium Debacle

I thought, “Alright, time to refactor most of these, merge them into macro services, and slowly ease back into a distributed monorepo.” Well, that plan was a swing and a miss. The architecture was heavily reliant on Debezium, CQRS, and Polyglot Persistence—oh, and did I mention there were 30 databases? Now, picture this: Debezium constantly checking each session across all 30 databases to feed data into Kafka topics. Let me tell you, this wasn’t just burning through money—it was flat-out devouring it like a hungry beast.

The Ultimate Test: Burnout and Resilience

Believe it or not, a lot of my problem-solving skills come from sheer spite. As Dana White once said, “Bet against me, I love it.” So, I dove into the project headfirst, and for a while, things were going steady—well, until the downspikes started hitting. You see, we only had a single production environment (because, naturally, running this architecture wasn’t exactly cheap), and that slowed down progress significantly. Improvements became more about just keeping things afloat.

I was on the verge of burning out like a phoenix, but spite kept me from accepting defeat. The overwhelming pressure of just keeping things running drained me to the point where I lost motivation for anything new. It became painfully obvious in my daily routine: you’re just coding to code. No passion, no progress.

Learning from the Abyss: A Turning Point

At that point, I realized maintaining this alone was becoming absurd. So, we decided to assemble an A-team to tackle the mess. And let me tell you, having two experienced seniors, an extraordinary medior, and an outstanding DevOps engineer by my side worked wonders. We started stabilizing things with surprising ease, even pushing out a few new features. But there was still one major hurdle: we had to get rid of Debezium in production to cut down on server costs. The problem? Doing that without any testing, while avoiding global chaos from downtime and database adjustments, was a nightmare.

The End of the Road: Letting Go

A solid plan was eventually drawn up—lots of planning around how we were going to reduce the constant session storage costs that were making RDS eat up money like it was going out of style. But here’s the kicker: it was going to take a lot of time, and time was something we didn’t have. So, one fateful day, the decision was made. The project was abandoned.

The Silver Lining: Lessons Learned and New Beginnings

In hindsight, I found myself being a bit hard on myself for calling it a “loss,” but then it clicked. We managed to keep that thing running—stably, for the most part—for nearly a year, with just a production environment and zero possibility of testing before releasing to users. That’s a damn good achievement if you ask me.

Looking back, I’m actually grateful for the experience. You really grow when you see what’s left for you to maintain after someone else has designed it. As a developer—and a software enthusiast—I’ve come to embrace this new mindset. KISS (Keep It Simple, Stupid) has never made more sense. It’s fun to show off your knowledge with patterns, complex architectures, over-abstracted code, wrappers, and libraries. But remember this: someone will eventually have to work on what you leave behind.

The Bright Side: Rediscovering Joy in Simplicity

After all that, jumping into a Nuxt project felt like stepping into heaven. It was actually maintained—dependencies managed, monolithic (bliss!), no over-abstractions, and TypeScript was supported out of the box. Types? Staging? Hell yeah. It was like rediscovering the joy of JavaScript while gradually making everything type-safe with TypeScript.

Then came Next.js, and man, it felt like a walk in the park. Even with turborepo and server components/actions, it was a breath of fresh air. After the chaos, this felt like smooth sailing.

Open-Source Contributions: Giving Back to the Community

In 2024, I also managed to dive into a few open-source contributions, and I’m pretty proud of what I accomplished. It wasn’t easy, but finding the willpower to actually get productive felt like a huge win. I worked on improving the @shopify JavaScript and PHP SDKs, helped Remix calm down their hydration chaos, and brought the Supabase JS SDK into modern paradigms. I also introduced an easier logger for the Swift driver, bridged the event loop for Swift WASMKit, and fixed TypeScript issues in Astro.

But that’s not all—I backported hot fixes for React community CLI breaking issues, helped with moving React Native to the new architecture, and contributed to improving build systems and the JSI.

I really feel like I gave back to the community this year, especially by staying active in discussions around Remix. I spent a good amount of time weighing whether Remix was actually a competitor to Next.js. Spoiler: it’s a fascinating debate.

Closing Thoughts

As we move forward into 2025, it’s important to take stock of everything that has happened, both the victories and the setbacks. Each challenge has shaped me into a better developer, and each lesson has been a stepping stone toward refining my approach to software. So here’s to another year of growth, collaboration, and learning—may we continue to build better systems, support each other, and enjoy the journey along the way.