
Rethinking the "Quick Refactor"
*"Hmm, look at that legacy code—I could refactor this, it doesn't look that complex."* Sounds like a classic junior mistake, right? Actually, I've repeated this mistake almost yearly for the past seven years. Every single time. And without fail, it turned out to be more complex than I initially estimated. First, there's the sales pitch to your manager. He has little interest in hearing why you want to touch production code used by thousands of paying customers, especially if the motivation is just aesthetic preference. Good luck getting that approved. Even if you secure the time, you're now on a deadline. Are you absolutely certain you understand every edge case in that old legacy system? No? Are there tests? Likely not. So you're relying on hope that your shiny new version won't crash. And when it inevitably does, you're the one accountable. Worst-case scenario? You're stuck in the middle of your "harmless little refactor," missing deadlines, stress levels spiking, working unpaid overtime to fix a mess you created entirely by choice. Refactoring isn't inherently bad. In fact, it's often essential for long-term maintainability. Low-risk refactors might include dependency upgrades, where newer versions patch vulnerabilities or reduce bundle size through features like tree-shaking. Other high-impact small changes include caching repeated DOM lookups in loops, extracting duplicated logic into shared functions, or converting nested callbacks to async/await for clarity. But be aware of what you're stepping into. If you don't fully comprehend the purpose and implications of the code, don't refactor it blindly. Always have a solid rationale, ideally with your manager's support. It's essential to understand why the code is shaped the way it is and which edge cases it's designed to handle.Pushing Side Projects Too Far
Everyone insists side projects are vital. They let you experiment, learn new technologies, and build confidence outside the pressure of deadlines. The trouble begins when you convince yourself that your side project is destined to become the next unicorn startup. My most "instructive failure" was an app called GGFinance. It started as my Master's thesis and evolved into months of late nights. The idea was solid—a stock portfolio simulator aimed at schools. Students managed fictional portfolios by trading stocks, the app tracked multiple financial metrics, displayed them in charts (people enjoy charts), and students competed against each other. I even created a YouTube video about it. The app itself is long gone now. I had plenty of examples to point to: eToro, XTB, various data visualization platforms. Clearly, my idea had to work. Or so I thought. My lesson was that having users doesn't automatically translate into revenue. Building a profitable product requires a genuine business strategy. Who would have guessed? I assumed that if I built it, customers would come and pay. No. What's needed is marketing, user research, pricing models, customer support... basically everything outside of development. I invested over 1,500 hours in that app. Was it worth it? Technically, yes. I was deep in optimization and problem-solving, and from a pure engineering perspective, it was the most demanding and best learning experience I've had. Financially? I was looking at negative numbers the whole time. Most projects don't succeed, and it's still surprising when our own doesn't. Putting more work into something doesn't guarantee its success. Sometimes you have to accept the loss and move forward. Regardless, I'll always recommend side projects. Not because they'll make you rich, but because they'll make you a better engineer. Company projects tend to stick to familiar stacks, patterns, and often stay away from "risky" experiments for solid reasons. It's easy to plateau. Side projects give you room to test a new framework, build from zero, and break things without consequences. You learn quicker because you're making all the decisions. Sure, it can be tiring after a long workday, but even a couple of hours per week will keep your edge sharp.Overestimating Your Own Abilities
My career started as an IT helpdesk guy just before my twenties. It was a small company, around 100 employees, with only two of us on the helpdesk. All user requests came in via email. It was difficult to track time, status, and who was handling what. And occasionally, an email would conveniently "get lost" if the request was particularly difficult. I was already learning some PHP, jQuery, and MySQL, so I came up with what I thought was a brilliant idea: build an internal ticketing tool, a mini Jira. This is where the Dunning-Kruger effect kicked in. I severely overestimated my skills. I thought, how hard can this be? A few forms, some login logic, a bit of CSS—done. Instead, I discovered just how little I knew, especially about concepts like asynchronous flows, multi-role authentication, and database design. For my first attempt, I designed the database with 5 tables, shipped the app after an unnecessarily long time, and felt like a genius. The app was ~functional. I got excited as it grew and the whole company gradually started using it. But feature requests kept coming, and as the only developer, I had to solve them all. Over the next two years, the project went through several iterations, and I even wrote a custom script to migrate my 5-table database into a new 25-table one. Fortunately, we had only 400 tickets at the time, but man, database migrations are the worst. This project had its ups and downs. What's fascinating is that even five years after my last commit, it's still in use, making it my most successful solo endeavor. But it came with plenty of frustration, a ton of learning, and many weekends spent coding while also studying at the University. I learned that before you promise the stars, you should make sure you understand your destination and have at least a rough idea of how to get there.Adopting Shiny New Technology
Once, I was assigned as the frontend dev on a greenfield project. We had the freedom to choose our stack. I had been experimenting with GraphQL on the weekends and loved its flexibility. You shape your own queries, and it generates TypeScript types. What's not to like? So I thought: "If it works in my toy projects, it'll be perfect for this large production app too." The backend team was on board. Management was convinced. We were ready to revolutionize things. Fast-forward 4–5 months. Everything works smoothly... on localhost. Then we move to actual servers, and suddenly, queries are slower than a government website. What now? Turns out GraphQL has its infamous N+1 problem, hammering the database with calls for every nested entity. We spent another 3-4 months optimizing queries and rethinking our approach. Now, similar to my point in the Overestimating Your Own Abilities section, what was my mistake here? For starters, I'd been learning GraphQL for only 3-4 weeks. I skimmed the documentation (who really reads the docs, right?) and used it on a small localhost project. We sold GraphQL to the company based on excitement rather than deep understanding, while disregarding some cautious voices from teammates. Remember, once you introduce a new tech into a project, you become responsible for it. Being the go-to person is not a problem if you know what you're doing. The issue is when you spend a couple of hours with a new library and assume you've mastered it. I should stress that I don't believe GraphQL is a bad technology. The company I now work for uses it in one project, and I've heard only positive feedback. It's a bit like using Angular without OnPush and then blaming Angular for being slow—the tool isn't the problem; the implementation is. This is really a story about me, a young, naive developer viewing new tech through rose-colored glasses, reading only the praise, missing the bigger picture, and convincing the team to take it to production.Not Reaching Out For Help
In my early days, my aim was to be a Java developer because, well, that's what was taught at University. Then one day at my job, I was given a small frontend task: build a dashboard with two pages. One to show external links as buttons, and another to display admin logs in a table. For an experienced developer, this would be 1-2 days of work. It took me 4 weeks. Why? Being new to the web, I had never heard of CORS, Proxy, JWT tokens, Cookies, Sessions, or Application State… and it was the first time I learned that JavaScript has libraries—Angular or React? Instead of asking my colleagues for help, I turned to Google and fell into a rabbit hole of fragmented information. There's a fine line between "I don't want to look stupid, so I'll google it" and "I have absolutely no idea what I'm doing." Junior developers often let ego get in the way. We'd rather spend 40 hours devising a terrible solution ourselves than ask a question and risk a 5-minute moment of embarrassment. Eventually, with the pressure building, I went to my superior and asked for assistance. He was frustrated that I'd waited so long to speak up, but we solved all the issues together. Now, as a senior developer, I've learned that admitting "I don't know" isn't a weakness. It's efficiency. It means I know when to find the right person and get moving again. It's also worth noting that not asking for help has an opposite extreme: asking too often. When you're new, questions are entirely expected. But be conscious of how you ask. You don't want to make your colleague into a personal search engine and just wait for the answers. Instead, always share what you've already tried or your current ideas. That way, your teammate can give more useful guidance, and you've proven that you put in some effort first.Lack of Project Management
I was thrilled when I landed my first junior programming job. I didn't question anything and assumed the team was following industry best practices. Well... not exactly. I had basic Git skills—commit, push, pull, which is still mostly all I do. But what surprised me was that our team of five devs all pushed straight to the main branch. No feature branches, pull requests, or code reviews. Just straight to main, with a "YOLO" attitude. As the project moved toward a major launch, the management held weekly demos for the client with new features shown each time. Those weekly presentations put intense pressure on us to release features quickly. I recall the day before one such presentation, I was finalizing my task. I was tweaking the checkout page and had commented out the payment button functionality for testing purposes. Since we had no PR review process, I forgot to uncomment it, made a commit, and pushed to main. Satisfied with my work, I shut down my PC and went home. The next day at the demo, the client noticed the payment button wasn't working. "But it worked last week…" they said. They check the Git history. Whose name comes up? Mine. Great. I got some feedback (gentle, but firm), which motivated me to carefully review every file change before committing from then on. I felt awful at the time. But now, looking back, the real issue wasn't just a junior dev breaking the build. It was a complete absence of process. No reviews, no QA, no checks. If a bug reaches production, it's rarely one person's fault. It means something in the team's workflow broke down along the way.When Emotion Gets the Upper Hand
Most of us aren't robots. Despite all the self-help advice and reminders to stay composed, there are times when frustration boils over and we blurt something we later regret. Two situations where this tends to happen: salary discussions and code reviews.
Consider the pay raise scenario. You're performing well, taking on additional responsibilities, leading initiatives, mentoring teammates. Your salary, however, doesn't move. Initially, you accept it. But weeks turn into months, and resentment quietly grows. Particularly in tech, where a colleague doing comparable work — or sometimes less — might be earning more. Then one day, you reach your limit. You march into your manager's office (or ping them on MS Teams), rattle off every grievance, demand a bump, and possibly hint at leaving.
Was that the smartest move? Possibly, you end up with the raise, but at the cost of strained relations with your boss. Even if you get what you want, the lingering friction could come back to bite you. A more effective route? Go in prepared. Document your achievements from recent months. Highlight the extra duties you've absorbed. Then, in a measured tone, ask whether revisiting your salary seems reasonable. Also keep in mind: even if you've been stewing for a long time, your manager is probably hearing this request for the first time. They won't have an answer ready. The goal isn't to back them into a corner, but to tackle the issue together.
This pattern shows up often, especially among junior developers. Early on, they feel fortunate to have a job and wait passively for management to propose a raise... which rarely happens. Here's the perspective shift: you chose this employer, and they hired you because you bring value. If they want to retain you over the long haul, this discussion needs to take place. Ideally, you'd have routine performance reviews where you outline your contributions. That's the natural moment to broach the subject. It might be uncomfortable initially, but these modest, candid conversations are exactly what prevent larger issues later.
Now let's talk about pull request reviews. There's a saying that code reviews are like standing bare before a mirror — all your imperfections visible. When you push a PR, you're usually fairly proud of it. You anticipate a few comments, but nothing dramatic.
I distinctly recall submitting a 200-line PR and receiving 50 comments in return. Whether I was annoyed is hardly worth asking. I nearly typed something I'd regret to that reviewer. Fortunately, it was still morning and I had enough restraint to pause. I stepped away, muttered a few choice words, then calmly scheduled a call to walk through the feedback together. Most of the comments were about coding style rather than business logic. That call stretched on and felt grueling, but we arrived at a consensus that worked for both of us and eventually merged the PR.
Over time, I've developed a more optimistic outlook: nobody genuinely wants to sabotage you. People focus on doing their job adequately, and sometimes their communication isn't the strongest. What felt like a personal jab might have just been them dashing off a quick reply. If anger flares, allow yourself to sit with those feelings, let them subside, and only then re-engage. Remember, it's always you and your colleague against the problem — not you against them.
NgRx for State Management
Around 2018, I recall a surge of enthusiasm for NgRx State Management. When your application grows, centralizing state with a library like NgRx can prevent code chaos and increase predictability. The reasoning was that adopting a battle-tested library minimizes the chance of bugs creeping in through bespoke state logic.
With that in mind, I dove into learning NgRx, and I encountered the notorious diagram. I stared at it for a week before convincing myself I had grasped what it represented.

I won't attempt to break down the concept here, but suffice it to say it's not exactly intuitive for newcomers. I was grappling with the shift from imperative code to declarative thinking, which is quite a mental hurdle.
During that period, we were migrating our custom RxJS Observable state management into the NgRx framework. This initiative was mostly championed by an external senior consultant, so we barely questioned his choices. I told myself I was missing the insight to grasp such superior logic.
Once the migration wrapped up, things started to feel strange. The project, which had been reasonably tidy, instantly ballooned in size. We ended up with three to four times more files, scattered across folders for actions, reducers, effects, selectors, facades, and sometimes even duplicate types. A straightforward state change now demanded edits in five separate files, crossing multiple abstraction layers. Worse, bringing new developers up to speed became a hassle. Rather than pointing them to a singular place with the logic, we had to guide them through a mental labyrinth tracing how state traversed the app.
In hindsight, the issue wasn't choosing NgRx. The failure was adopting a robust tool with an unclear grasp of the paradigm shift required, plus undervaluing the overhead it introduced for a somewhat small team. NgRx is not inherently flawed — it excels when applied appropriately. You can own the finest hammer available, but that won't help if you don't know how to swing it.
With years of hindsight, I've noticed NgRx proposing Component Store and even NgRx Signals as far more lightweight alternatives to that earlier architecture. After a pause, I revisited it with fresh perspective and published an article on Angular State Management - Imperative, Declarative, Ngrx and SignalSlice
Personally, I've worked on frontend projects under 500K lines of code, where I'd lean towards a bespoke signal-based approach to handle application state. That said, I now recognize why libraries like NgRx exist and where they truly thrive. In massive applications with numerous developers, rigid separation of concerns, consistent flows, and centralized debugging become essential. NgRx's declarative framework can impose uniformity across teams, simplify testing, and guard against unintended side effects. Ultimately, it's worth experimenting with to form your own judgment.
Key Takeaways
Sincerely, and a bit regretfully, I could keep listing the missteps I've accumulated. But the central lesson is this: everyone errs. Sometimes mildly, sometimes spectacularly. That's precisely the path to growth.
What distinguishes a senior developer isn't having all the answers. It's understanding which poor choices to steer clear of because you've already faced the consequences. Experience teaches you not just what to do, but what to avoid doing.
So embrace failure. Then fail with more wisdom. Maybe someday, you'll be composing posts like this after recovering from your own failed side endeavor. I hope you found these anecdotes useful. Don't hesitate to share your perspective, find more of my work on dev.to, connect via LinkedIn, or explore my Personal Website.

