How I received 4 salary raises in 2 years as a Software Engineer

·

22 min read

Or a better title would be: "how to be a Rebel at Work and keep improving the craft".

The original post was published at iamtk.co.

Disclaimer:

  1. these ideas and insights come from a privileged person working in a very privileged industry.
  2. my intent is not to show off, but to share my experience and I hope you can steal some ideas.
  3. it's ok to see money as a valuable capital in your life, but I'll focus on how I improved my craft in this post.

Before telling my experience

In this essay, I'll talk about skills, experiences, opportunities, and mindset. Basically how I became better at my own craft.

My focus was always on the journey and I didn't intend to grow at the company. This was not my goal. I actually didn't have a real goal, just wanted to have fun while working, search for autonomy and control, and have a space I could learn a lot.

With that in mind, my experience may not help you "climb" the Career Ladder. But I hope you can steal some ideas and use them in your favor for better working life.

Also, if your goal is to grow at the company, climb the career ladder, and get raises, maybe I'll write about it in the future, but here are two (shallow) advice:

  • Understand the career ladder (if your company has one): to be able to get promotions, you need to understand where you are at and what are the expectations for the next level.
  • Work with your manager: use One-on-One meetings to sync the career ladder expectations, receive feedback, ask for projects you could work on. Everything that can help you go to the next level.

There are many other things you can do to get raises, but, for me, these are the fundamental pieces that will help you take the first step. And as I don't want this essay to focus on promotions, I'll probably write a separate article for this topic. But you can find awesome content on the internet that is probably better than my future one.

My Experience

External Factors

To start, I have to say that I had important External Factors. QuintoAndar is one of the fastest-growing startups in Brazil. Today it's valued at $5.1 billion. It's an innovative company in the real estate industry, and it has a business model that works well in Brazil.

The fact that it's a company that's making money, was invested a huge amount of capital, and keeps growing, it's a very important factor when it comes to getting raises and promotions.

Besides this, it's a company that attracts real talented people, not only in engineering but in the product and other organizations too.

IMHO, the culture is great for engineers as I always felt that it was a safe place to expose and discuss my and new ideas, to share my honest opinion on what was working or not, and was always incentivized to challenge the status quo.

So these are the important external factors that had nothing to do with my skills and work:

  • QuintoAndar is a fast-growing company
  • It kept growing financially over the years
  • Real talented people
  • Great culture (but not only) for engineers

Achieving my team's goals

Before anything else, my focus was always on my team and our quarter goals. It was truly important to me that I understand the team's goals, the business metrics we should look at, and why we were doing this list of features.

To have everybody on board, we had a Notion page with everything business and product-related to our team. I also created a dashboard with all the important pages we had in the Amplitude platform to be easier to access key metrics.

Understanding why is just the first step. As engineers, one of our responsibilities is to help and come up with solutions for the how.

Collaborating with the product manager, the designer, and the other engineers here is key to succeeding as a team. I think this part not many people talk about and it was always a bit fuzzy for me when I first started working in software engineering. Collaborating means a lot of different things here, but I'll list some ideas I executed in the past:

  • Ideas can come from different places: your manager, the PM, the designer, or any other person outside your team. After understanding the idea (and most importantly, the problem), you help shape and polish the solution with your engineering background and knowledge from the current system you're working on.
    • You probably understand the pain points from the system you're working on.
    • With your background, you can think of different solutions: each with its own effort and time you and your team will be needed to spend on.
    • Negotiate to have more time to polish the chosen solution after the implementation that needed to be deployed faster to the real user but lacked a bit of the engineering best practices.
    • Or better, negotiate to have time to deliver the feature or product with best practices already built-in.
  • Ideas can come from you: a feature, a product, or an improvement that you saw that could improve the user experience and business metrics. Later, we'll talk about my experience leading the web performance project and being a product-minded software engineer.
  • Create a safe space to collaborate: it's easy when the company's culture already creates this space that you feel safe to discuss ideas, come up with your own, or disagree with others. Having a more and more diverse team was important to enrich the discussions we had in the team, and having a safe space is the building block that enables people to discuss without fear of judgment.
    • Creating space by asking everybody in the team to ask questions, discuss, and share their opinions.
    • Actively listen to people, care about what they are saying, and document the insights to use to polish the ideas discussed.
    • Having better processes for developing products: a space to discuss the strategy, a space to discuss quarter's goals and metrics, a space to discuss the engineering challenges and architectures/solutions.

The thing is, as you mature as an engineer, you not only code to deliver products but you collaborate in all aspects of software engineering. You understand that making the team, the processes, the delivery, and the dev experience better are part of your "responsibility".

Challenge the status quo: everything can be improved

I need to emphasize that the QuintoAndar's culture not only expected me to challenge the status quo but I was always incentivized to improve – or create awareness – about everything that was suboptimal. So it was always an environment where I could question everything and experiment with ideas and then improve things that were not working or could be better.

When thinking about improving stuff in a company, the goal is to make the organization better. I could think of processes, technologies, the team's culture, the developer experience, and so on.

My idea was always to do things that don't scale first: focus on my team, try experiments, learn with this process, and improve it. Do this cycle until the idea gets matured. When I felt it was ready to scale, I could share it in more broad scope, like a tribe (a set of squads/teams) or for the whole organization.

A good solution always comes up with a well-defined problem (or a well-defined thing that could be improved). This is why understanding the problem and the context is so important. Living and breathing the engineering problems on a daily basis gave me a lot of understanding of how things worked and enabled me to think of solutions to make it better.

As I was working in a big tech company, the technologies, patterns, and conventions are extremely important to make us move fast but always with quality in mind.

My first initiative was to create guidelines about how we used React, optimizations, immutability, and testing in JavaScript and React. Guideline documents are a nice initiative because first, we can normalize the conventions and patterns cross-company, and second, they gave awareness about these topics and as engineers, we could discuss the conventions we wanted to adopt and formalize. I liked the whole process, mainly because it was always nice to receive feedback, different views, and insights from other engineers and we could come up with great solutions for frequently problems we face on a daily basis.

With this first initiative, I gained confidence that I could improve more and more things in the engineering scope. For every problem that I faced, I documented the solutions and patterns that I came up with and shared them with other engineers.

I remember when we didn't have the opportunity to use Hooks in our PWAs. So I made some experiments (React Hooks, Context API, and Pokemons) and shared them.

Regarding JavaScript patterns, I also experimented with some ideas on Closures and Currying, Internationalization abstraction in React, and Functional Programming.

As our codebase was getting more and more complex, it started to get difficult to reason about it, mostly the state management part, which we were heavily using Redux.

"Typing" our state management gave us more confidence and make it more clear how data was structured in the app.

Choosing TypeScript to handle this made me study a bit more and create a Mental Model to think in TypeScript. As we were using React in almost all codebases, it was important to have examples of how React and TypeScript can work together.

Testing applications was a topic people were always interested in the company. We had mini guilds to discuss these ideas and create patterns and conventions we wanted to use. I could share my two experiments: TDD, JavaScript, and React and Basic Recipes for React Testing Library. I think TDD is a more personal process, but using the testing library was our default choice to test our applications.

Technology is always changing and improving. We saw many libraries coming up and two gained our attention: react-query and swr. I could make experiments with both and my colleague and I came up with an Architecture Decision Record (ADR) for react-query. We saw the potential to use this pattern and replace redux-pack and redux-saga, which were bottlenecks in terms of performance for us. Also, react-query brings a more intuitive approach and focuses on the server cache challenge.

Besides technology, we can think of developer experience. Engineering time is getting more and more important.

We recently found that the new 2021 M1 MacBooks cut our Android build times in half.

So for a team of 9, $32k of laptops will actually save $100k in productivity over 2022. The break-even point happens at 3 months.

TL;DR Engineering hours are much more expensive than laptops!

— Jameson (@softwarejameson) November 3, 2021

But in my opinion, it's not only important but can be crucial for many companies that are scaling their business. You don't need a separate team or a platform squad to improve the engineer's productivity, we as engineers can always design better processes and solve productivity bottlenecks. It's up to us to talk to our managers, allocate more time for this type of work, or even create a new team from scratch.

I did work on developer experience and I need to say that I had a blast. I wrote a whole piece about this experience if you want to take a look at it: DX & Software Maintainability in Frontend Engineering.

But in summary, I worked on the engineers' pain points at that time:

  • Monitoring: instrument the new system, create dashboard links, document how to use monitoring systems on a daily basis.
  • Tests: experiment with new testing toolings, share the insights from these experiences, write guidelines and examples on how to use them, show different patterns.
  • CI/CD: not only optimized the CI builds to tune developers' productivity but also automated the release process. Before it was GitHub tags, now they just need to merge the PR and it automatically deploys the new change.
  • Code Formatting: now using prettier together with ESLint's rules. I was able to format the whole codebase with prettier in less than a week. And with confidence as we had quality automated tests and our monitoring system backing us. Also was able to implement a pre-commit hook to run prettier and ESLint for every commit made on the repository.
  • Web Performance: I had the opportunity to work on a web performance project before, but in this case, I could work on instrumenting performance tooling to collect real user metrics (Core Web Vitals).

Monitoring and Tests were the building blocks to do more experiments, refactoring, and change code with confidence. Formatting code automatically was a huge gain in letting engineers discuss business rules and architecture instead of debating if you need to add a semicolon or not. Web performance tooling was the building block to measure any initiative related to improving the performance of that software. Making CI faster improved the experience for every engineer that worked on that project. Building a Continuous Delivery also makes the developer experience smoother.

And the last piece in this Challenge the status quo part is Knowledge Sharing.

For me, everything that I learn, research, or experiment, I like to document and share. The document format can vary. It can be an article, a guideline, a Notion document, slides to use for tech talks, or simple notes on my Moleskine to be used to create content based on this draft.

I've been doing this for 8 years now and everything is documented here: writings.

It's a way to share my learnings with my teammates, but also share ideas with the tech communities. Having this process helps me craft my thoughts and learn more about each topic I experimented with before.

First writing, second any kind of content I want to share. Writing down and organizing the ideas and experiments is the foundation to create any other content. With the written article, I basically detailed everything I wanted to share and it could turn into guidelines (the example here was the testing recipes), engineering critics, or slides for a tech talk, as I did for Web Performance Improvements.

But the thing that I liked the most was turning my writings into topics to discuss with the team. We had a group meeting called Guildinha, or Little Guild, and every engineer could plan the meeting with a topic in mind. It was always an informal meeting to chat, discuss, and learn from each other.

With more knowledge and experience I could also mentor informally and formally my colleagues throughout the 3 years I was working there. It was always nice to talk to other people, help them grow in their careers, and impact their work somehow.

Improving my Craft

Among all topics I'm covering in this article, this is what I find the most interesting: Improving my Craft.

I partially wrote about this before in two essays:

I know I'm not a machine, but I'm constantly looking for ways to learn more and gain more knowledge about things I care about. Every day. Every time. Forever.

I've been rethinking the way I learn in my free time and usually, I have three ways

  • Fundamentals
  • On-demand
  • Local Maxima vs Global Maxima

When I think about fundamentals, I think of First Principles. What are the building blocks of software engineering? What are we absolutely sure is true? And reasoning from this principle, we can understand and solve more difficult and complex problems.

In software engineering, we have an ocean of things we can learn. When I was a backend engineer, my focus was on understanding APIs, system architecture, automated tests, and databases. For each topic, I could go deep and understand the building block of each one of them. With a better understanding, I could link this knowledge (or "connect the dots") and solve more difficult problems in backend engineering.

This worked the same way for frontend engineering. I started with HTML and CSS and then learned more about JavaScript. Now we have other things we need a better understanding of to do the work (or at least more complex work) like build systems (the compilers and bundlers), automated tests (for components and integration), browsers engines, and so on.

Knowledge is infinity and I won't learn everything but reasoning from first principles helps me not only solve complex problems but also understand what are the knowledge gaps that I'm missing.

On-demand way of learning is basically when I have a new challenge at work or in my side-project and I need this specific kind of knowledge to solve the problem. It happened when I needed to understand monitoring, testing, and web performance at work and it's also happening on my current side-project which I need to have a better understanding of CMS and text editors.

And Local Maxima vs Global Maxima is one of the things that I learned these days. It was very counterintuitive for me but as I'm doing more and more it got clear to me how important it's to diversify your knowledge portfolio.

If you're a JavaScript engineer, the obvious choice is to keep learning about JavaScript but soon you can get trapped in the local maxima. What I did was to first get one step away from my comfort zone and learn TypeScript and how to get the best out of type systems. My next step was to learn more about browsers, algorithms & data structures. Now I'm investing my time and effort in learning about compilers, how bundlers work, and Rust. Everything I've been learning has a direct or indirect impact on my work and how I think about engineering.

At work, it was no different. My approach was to actively look for feedback, from my managers and peers, and figure out how to be a better software/product engineer.

Actively looking for feedback is a habit that I wanted to start earlier in my career. In the early days, my thoughts were "feedback is great, I'm always open to receiving feedback". But it was not enough. I did at my last job was to have a weekly meeting with my manager and always ask about her perspective about my work on that week:

  • The things I was doing well and should keep doing
  • The things I was doing ok and could improve or could do more
  • The things I was doing were not that great and could improve

I think these bullet points are a good starting point to discuss things I could learn, do, and build habits.

The other thing was to provide feedback and ideas to make the project better. I had a weekly log about the things that could be better and I shared it with my manager to discuss how to implement them in our processes and project's codebases.

Another effective way to receive feedback is to work on your IDP (Individual Development Plan). I wrote about that before but the idea is to develop a plan for your (career) growth. With this shared document, I could always debate with my manager about the path I was following, what I was learning, what were things I was interested in, and receive feedback and advice on how to improve my actions and habits. It's also a nice way to become more self-aware and share with your manager the things you like the most and possibly receive projects that have the intersections of your skills and interests. I really liked working on my IDP and I came up with a public version of it to share with my teammates. Everyone knew what I was learning and it was the starting point to discuss and share more knowledge within the team.

But It's ok if you don't want to create a plan to grow in your career. There are always other ways to incentivize receiving (and giving) feedback in your team. To receive feedback from my peers I first gave feedback (informal and formal) for each one of them and kindly shared that if they had time, I would be happy to receive feedback too.

Regarding figuring out how to be a better product/software engineer, there are very interesting articles about product-minded engineers out there but I'll give my two cents on this topic through my lens and experience.

For me, the first step is to understand the product you are working on.

Is it a product for final users?

  • who are the clients?
  • can I understand their behavior through data?
  • talk to designers who interviewed them, and have documented insights.
  • how does the business work?

Is it a product for internal stakeholders?

  • what are the goals of these stakeholders when using this product?
  • what are the missing functionalities?
  • what are the general complaints?

Is it a product for engineers?

  • what's their current workflow?
  • what are the things they are happy about?
  • what are the things they are angry about?

But for all three (and any other) groups, we can always think about UX (what are the UX pain points?) and find ways to help them achieve their goal.

Figuring out which product you're working on is a good starting point. Asking a lot of questions about the business, the users, and how it is used are also tools to gain more knowledge about the product.

The second thing I usually do is to understand the next steps, the OKR, the goals of the team regarding the product. Understanding why we are creating this feature X, the related metrics we want to achieve, and actively participating in discussions to debate what and how to do things.

Having open doors to engineers in these meetings is awesome because we can not only help thinking about product ideas but also give insights into the software underneath the product. As we have the engineering and the software background, it's very useful when creating strategies and debating engineering X product tradeoffs.

Don't miss the opportunity to learn more about the product and actively participate in strategy and planning meetings if it's possible.

Challenge yourself with interesting projects

Interesting projects can be the building block for your learning experience at work. While doing a challenging project, you'll probably learn a lot. Things you don't know and need to search and learn. Things you know and could do the best work. After finishing this kind of project, it's nice to do a retrospective on things that went well and things that you could do better. It's always a learning experience.

I like challenging projects because, first, I like challenges. Second, because I always have fun at work when I have the opportunity to learn new things. And finally, because I like to look at my past self and be proud of the work I did.

Things I did:

In all these projects I could always learn a lot. Building the photographers app was the first time I worked with serverless functions and React. Building the affiliate product was the first time I worked with Clojure and the payment system. Improving web performance was the first time I worked with performance in the web and build tooling (mostly Webpack) in depth. Thinking about DX gave me a macro perspective about the engineer's workflow and I can apply this knowledge in other places as well.

Challenging projects are always great tools for self-improvement as they are opportunities to keep learning and improving your craft. Seek interesting projects and keep learning. The feeling to look to your past self and be proud of your decisions and development is amazing.

Keep a Journal

I have a habit to document everything. From things I'm learning to book's notes. From articles ideas to daily journals. Journaling is part of my day and it helps me think and opens space to reflect on the things I did in the past.

These are a series of ideas I came across and you can use in your favor as well:

Document all the things I accomplished

  • What: What was the project I was working on, the problem I was solving, or features I implemented.
  • How: How were the solution and the architecture decision, which PRs I worked on, what were the tradeoffs, how the team worked together, and what was my role in this whole project.
  • Learnings: What are things I would do differently – it can be architecture, solution, process, delegation, communication, prioritization, anything that could be improved and you can use it as a learning experience for another project.

Understand the impact of your work

  • The first things that should be 100% clear to me are: what's the problem we are solving, why (this usually come from the PM, designer, or business people), and how we should solve this.
  • With that in mind, I keep my eye on the important "metrics":
    • business/ux: I work together with PMs and designers to understand the business metrics and OKRs we'll be looking at.
    • engineering: performance, build time, error logs, monitoring systems.
    • dx: feedback from my teammates about what are the pain points and create initiatives to solve these problems.

Weekly documents

  • As I told you, I document everything. It's a habit. At the end of the week, I tend to compile all my daily documents in a weekly document.
  • It's cool to see what I've been working on, what I've learned, and the challenges I had to overcome.

Quarter document

  • It is also great to document in this way because I can just compound all notes I wrote at the end of the quarter, and it works like a report document for everyone at the company that wants to know what I've been doing.
  • This document also serves as a "brag document" to talk to your manager.
  • It's easy for your manager to understand your accomplishments.
  • It's easy for your manager to use this document to work on your promotion (if you're interested in this).

This is why I think documentation and journals are powerful. Making it a tiny habit has a huge impact after compounding all your work. As engineers, we tend to focus on the little things in our daily lives, but having this macro vision about our work is rewarding. It makes me proud and aware of my self-development.

Final words

As I wrote at the beginning of this essay, even though the title is a true story and money is a valuable and important capital in our lives, I wanted to talk about skills, experiences, opportunities, and mindset. Basically how I became better at my own craft. And I hope this piece can help you in some way in your career. Feel free to steal some ideas you find interesting and apply them in your life.

Finally, I need to say Thanks! to QuintoAndar for its great culture and the amazing people I worked with: my peers, my managers and leaders, and stakeholders that enabled me to be the best version of myself. I only have gratitude.

Resources

Writings

Series

Learning

Interesting resources