Leading teams and building platforms across different contexts made me rethink. Some opinions proved reliable and continued to guide decisions. Others failed under pressure or became blockers. Along the way, I picked up new ones, usually the hard way. This post reflects how my thinking has evolved: what I still believe, don't, and have learned to value.
Kept
- Typed languages are better. In my professional life, I've written a lot of code in Python and Java. I wish I had gotten types later in all the projects that started as a small Python script. Refactors become a lot easier with them. You need fewer tests. With hundreds of people contributing, big codebases are a mess without types. That's why Shopify wrote Sorbet; Meta invested engineering time in Python's type-checking, Microsoft created TypeScript, etc. All of these have something in common. As codebases grow, types are one of the most valuable tools for refactoring. Even if you start with a duck-typed language, you realize it later.
- Engineering managers must be technical. In many cases, brilliant Individual Contributors (ICs) get "promoted" into management roles just to fail spectacularly. Sometimes, this is due to a non-existent IC career path. In other cases, other leaders push them due to circumstances. However, past software engineers were the most successful EMs I've worked with. I also worked with a fair amount of non-technical EMs. Most were great project managers who kept their team united or reasonably happy, at least for a while. If you don't understand technology enough, you're at the mercy of the ones who do. Is <what the team is building> that complicated? Is my team following good industry standards? Are the latest trends in AI true or just hype? Sometimes, you can get the correct answers by asking good follow-up questions, measuring the right things, or having a checklist. But that doesn't survive the test of time.
- Continuous Deployment is key for high-performing teams. I wrote about it ten years ago. Testing, automation, and continuously integrating/deploying software is the way to go. Having good forcing functions to keep your iterations small, using feature flags, and shipping daily. If you do that consistently, no one will ask, "How much will it take to build X?". They know you'll ship the first version soon because you deliver small chunks, measure, and improve. No great engineer wants to wait hours for their build to finish and two days before their code can reach production.
- Writing is a superpower. Condensing thoughts in one document, iterating on it, and distributing it with zero marginal cost does wonders for you, your team, and your company. Sometimes, writing is enough for me to discard an idea and iterate over it. At some point, you can just link back to the document. Examples:
- Q: "How do we tackle promotions after <reorg N+1>?". A: "You got the document our leadership team wrote last year, and we may start from there."
- Q: "Why are you working on <this thing>?". A: "Because it directly relates to our strategy. Here's the document".
- Hiring QAs is dysfunctional,as I have explained before. In general, you should invest in good automation and observability processes. Hire software engineers who are product-minded and understand their users. Fix your organizational problems before throwing QA at them.
Let go
- Scala is the best JVM language. After all the Scala 2-3 drama, they even saw the pain of Python, for God's sake! — and JetBrains polishing Kotlin, being pragmatic, it's clear that Scala lost its way from being a "better Java." A big part of the community strives to write a "Haskell for the JVM," whatever that means.
- Deadlines are bad. They create constraints that allow engineers to show their creativity. Deadlines are great because they attack overengineering and complexity. They give teams a goal, creating a virtuous loop of delivery, impact, and happiness.
- Invest time in fine-graining tasks to avoid blockers. While this is often a complaint developers make, it does more harm than good. If you go fine-graining tasks before taking that work, you have a moving target: maybe context changes or requirements change. At the same time, if you invest and go through the code, data model, and architecture to make it worth it, why not do it immediately? The best developers I've worked with preferred the autonomy to understand the scope and the why behind a need. Then, come up with a plan and discuss trade-offs to ship things. That creates a forcing function to solve the right problem with the right amount of engineering.
- Test coverage, unit tests, and the test pyramid are non-negotiable. While unit tests provide value, they often conflate behavior with internals. Hence, you end up with a super large test suite that, in every refactor, you also need to refactor. I'd still keep them for core business logic. Other than that, I'd favor more integration tests — either mocking the data layer or using docker — that are fast to run nowadays. I'd completely remove end-to-end tests and favor the usage of feature flags, progressive rollouts, and good observability in place.
- You should have a preproduction environment just like production. It takes a non-trivial amount of engineering to achieve something like that. You must maintain two production-alike systems for your users and development teams even when you do. Whenever I saw a team battling against deploying "all the microservices" in a preproduction environment (N x M version problems) or creating ETL processes to have production-like data, it became a full-time job to maintain it. Please check my post on disasters I've seen in microservices.
Picked up
- Support is critical for internal Platform teams. If your team builds anything as a service — a chat component, Kubernetes, Kafka as a service, etc. — giving great support is your ticket to being considered business-friendly and trustworthy. These are two key characteristics if you want to influence how other teams build and ship software.
- Give support right where people are. If people ask a question in Slack, you first ask them, "Can you please create a ticket for me?" You're putting the process in front of the user with the same information they already gave you. Do it for them or automate it away. That, paired with #1, shows user centrism, and you get happy users. I must thank Alex Moleiro for these two learnings.
- Shipping builds momentum. Complaining creates distrust. Whenever I saw engineers come to a team and start shipping from day zero, it created momentum for them. After observation, they got the trust to share improvements with the rest of the team. Often, these improvements were not just philosophical discussions but actual implementations, with small steps. On the other hand, when I saw engineers complain about how tech debt was not sustainable and how everything was broken without shipping on time, exploring and presenting alternatives, the team got averse to this person.
- Infrastructure teams must ease migrations as much as possible. This one may be a bit controversial. I've seen many infrastructure teams say to 50+ development teams, "Hey, you need to migrate from A to B. The deadline is in three months." Then, another infrastructure team comes with another migration, timeline, etc. Leveraging the right interfaces, creating automation, and moving teams seamlessly across infrastructure are key for successful migrations. Whenever there was a link to a three-page document and a deadline, the migration took much more time and effort and generated more frustration.
- Brag documents are better than your performance review process. Engineers are great at doing things, and, more often than we'd like to admit, they're not keen to talk about the impact of what they do. Then, when the performance review comes, they think a promotion will magically happen. The usual performance review process is based on peer feedback with generic questions on "What am I doing well? What can I improve?" leading to sterile praise and no actionable on development areas. Why are brag documents so good?
- They force you to consider your impact and whether that refactor had a positive ROI. If you talk about cost savings, how much did you save? Have you weighed that against the opportunity cost? What have you leveraged from others' work? What others leveraged from yours?
- They create a framework for your manager and peers to give precise feedback about a specific situation or impact. This leads to better development talks than asking generic questions.
Which opinions have stood the test of time for you? Where have you changed your mind? And what lessons have reshaped how you build, lead, or decide? I'd be curious to hear.
— João
I’m building RotaHog, an Honest SaaS for managing team rotation schedules (on-call, support shifts, release duties, etc.). Try it if you're tired of hacking spreadsheets or Slack threads together. I’d love your feedback!
If you enjoyed this article, consider subscribing to the newsletter and buying me a coffee.