Skip to content
ExponaBLOG
ENGINEERING CRAFT · DAY 089 / 100

Mistakes I made as a junior developer: a practical guide

So you can skip a few.

Expona Admin6 min read

Opening

I spent my first two years as a junior developer optimizing things that didn't matter, asking questions too late, and shipping solid work that nobody knew about. Looking back now with 5.5+ years under my belt, I can see exactly where I wasted time and credibility. The mistakes I made as a junior developer were less about technical skill and more about judgment—knowing what to optimize, when to ask for help, and how to make my work visible.

If you're earlier in your career, you don't have to learn these the hard way. I'll walk through each one with examples from real production systems I've worked on, and what I do differently now.

Optimizing Code Nobody Ran

My first serious mistake happened three months into my first job at an e-commerce platform. I inherited a payment reconciliation job that ran once a day. The function looped through transactions and did a database query inside the loop—textbook N+1 problem. Classic junior move: I spent a full week refactoring it to batch queries, add caching, reduce the loop from O(n) to O(log n), all that good stuff.

The job took 45 seconds before. It took 8 seconds after.

Nobody noticed. It ran at 2 AM.

Meanwhile, the dashboard users were complaining about latency on the transaction list page. That endpoint was getting hammered 200 times a day by actual people. I could have made those people's lives better in an afternoon, but instead I optimized a background job in a datacenter.

This taught me the hierarchy of optimization:

  1. User-facing, high-frequency code first. Dashboard queries, API endpoints, real-time features. These have impact.
  2. Expensive resources second. Database connections, third-party API calls, memory under load.
  3. Background jobs and scheduled tasks last. They're measured in minutes and seconds of human attention, not milliseconds of user experience.

Before I write a single line of optimization code now, I ask: How often does this run? Who waits for it? What's the actual cost of the current version? I use APM tools, I look at logs, I measure. Optimization without data is just scratching an itch that might not exist.

Not Asking Questions Early Enough

Six months in, I was assigned a feature to add notification scheduling to our CRM platform. The requirement was "let users schedule notifications to send at specific times." Straightforward, right?

I spent three weeks building a solution. Scheduled jobs with Kafka, timezone handling, state machines for notification lifecycle, the works. I shipped it, and within two hours a senior engineer asked me: "Why didn't we just use the SQS delay queue we already have?"

We could have sent a message to SQS, told it to wait four hours, and called it done. No state machine. No new infrastructure. No three weeks.

The issue wasn't that I didn't know about SQS delays. The issue was I didn't ask anyone before I started. I assumed the problem was harder than it was, I assumed I needed to prove something by building something complex, and I didn't want to look dumb by asking what might have been obvious to someone else.

Now I ask questions before I start designing anything:

  • Has this problem been solved before in the codebase?
  • What systems or libraries do we already have that touch this domain?
  • What's the constraint nobody mentioned—deadline, scale, legacy compatibility?
  • If I had to do this in one day instead of three weeks, what would I cut?

A five-minute conversation with the right person saves weeks of work going down the wrong path. Junior me thought asking questions made me look weak. Senior me knows that shipping the wrong thing is worse than admitting I don't know something.

Rewriting Instead of Understanding Old Code

Year two, I joined a travel platform team that had a complex booking engine written by someone who'd left the company. The code was dense, had minimal comments, and took me three days to follow. My instinct: rewrite it.

I convinced my tech lead to let me rebuild it from scratch. "It'll be cleaner, faster, and I'll actually understand it," I said. I spent six weeks on it. When we tested it against the old code, we found seventeen edge cases I hadn't handled. Refund scenarios, multi-currency exchanges, inventory rollback on timeout. All things the old code did because the author had lived through production disasters.

I had to revert and spend another two weeks reading the original code properly, with git blame and Slack history to understand the "why" behind each decision.

The rule I follow now: before you rewrite anything, you have to understand it well enough to explain why the current version is wrong. If you can't articulate the specific problems—performance, correctness, maintainability—then you don't understand it yet.

When I do need to refactor something, I do it incrementally:

  1. Write tests against the current behavior (even if you don't like the behavior).
  2. Refactor small pieces, keep the tests passing.
  3. Let those changes soak in production for a while before the next piece.
  4. If something breaks, you've only changed a small piece, not the whole system.

Understanding old code is slower than rewriting it. But rewriting without understanding is how you ship bugs that hurt real users. On the ride-hailing platform I worked on, bad refactors of driver allocation logic cost us money in inefficient routing for weeks before we caught it.

Doing Great Work Silently, With No Visibility

This is probably the most expensive mistake I made as a junior developer. I shipped good code, fixed tricky bugs, delivered features on time. I rarely talked about what I was doing.

I was quiet in standups. I'd say "working on the payment refund flow" without giving context. I didn't write one-pagers on designs I'd implemented. I didn't document why I'd chosen one approach over another. I just shipped it.

For performance review time, my manager had almost nothing to point to. She knew I did stuff, but couldn't quantify impact. When promotion time came, there were senior developers who were equally skilled, but everyone knew about their work. They got promoted first.

Now I'm deliberate about visibility:

  • In standups, I mention the impact: "Fixed a query that was doing N+1 lookups—should cut dashboard load time by ~30%."
  • For designs I'm proud of, I write a one-pager in Confluence with the problem, the approach, trade-offs I considered.
  • In PRs, I explain the why, not just the what. Future me will thank me, and so will anyone reviewing my code.
  • When I mentor juniors or pair on complex problems, I mention it because mentoring is work, and it should be visible.

This isn't about self-promotion or being loud. It's about giving your team and your manager the information they need to understand your contribution. If they can't see it, they can't value it.

Common Mistakes

  • Premature optimization: Optimizing code paths that barely run, or that aren't actually a bottleneck in production.
  • Assumption-driven design: Building a solution before validating that the problem is as complex as you think.
  • Big rewrites instead of incremental refactoring: Throwing away code because it's old, rather than understanding why it's structured that way.
  • Silent shipping: Doing solid work but not giving your team visibility into what you've done or why it matters.
  • Not reading git blame or Slack history: Missing context about why code exists, leading to regrettable refactors.
  • Solving problems alone: Spending days on something that would take an hour with a senior developer's input.

Key Takeaways

  • Optimize what matters: user-facing code and expensive resources first. Measure before you refactor.
  • Ask questions before you design. A five-minute conversation can save weeks of work in the wrong direction.
  • Understand before you rewrite. If you can't explain why the current code is wrong, you don't understand it yet.
  • Make your work visible. Ship great code, but also communicate the impact so your team and manager can see it.
  • Prefer incremental change over big rewrites. Small changes are easier to test, easier to revert, and easier to learn from.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles

Mistakes I made as a junior developer | Craft | Expona