Are You Focusing on Output Over Outcomes? Rethinking Software Development

As an engineering manager, you’re tasked with building awesome teams. You work tirelessly to help keep projects on track, meet deadlines, and deliver results. But lately, something feels off. Your team is undoubtedly busy, even productive by conventional measures. Yet, you can’t shake the nagging feeling that all this activity isn’t translating into meaningful impact for your business or your users.

If this resonates with you, your team might be caught in a cycle of prioritizing output over outcomes. Let’s explore what this looks like from a leadership perspective and why it’s a critical issue to address.

Signs of the Problem

  1. Measuring Work Alone: Your team’s success is measured primarily by output – story points completed, tickets closed, features shipped. But what about the outcomes? Are you tracking the actual value these activities bring to the business?
  2. Lack of Feedback: Features are developed, shipped to production, and marked as “done.” But then… silence. There’s no mechanism in place to gather feedback on whether these features are successful or even used.
  3. Team Disconnection: Your developers are “shielded” from talking to business people. You might have heard the phrase, “Don’t interrupt our precious engineers’ time.” But this protection comes at a cost – disconnection from the very problems they’re trying to solve.
  4. Deadline-Driven Development: Your team is constantly working towards deadlines handed down from above. The problem? No one on the team understands where these deadlines come from or why they’re important.
  5. Product Overwork: Your Product Managers are spending so much time writing detailed specifications that you’re considering hiring people whose sole job is to create detailed specs for the engineers. This level of detail might seem helpful, but it can stifle creativity and problem-solving.

The Round Corners Saga: A Case Study

Let me share a story that might hit close to home. Your team has been working on a new user interface. In a recent sprint review, you’re surprised to learn that one of your engineers spent five days ensuring text boxes had perfectly rounded corners across all browsers and devices.

Proud of their attention to detail, your developer showcases the feature. But when you speak with the product owner, you discover that the round corners weren’t even a requirement – they were just a default style in the design tool’s mockups.

Five days of a skilled developer’s time, spent on an unintended, unnecessary detail. As a manager, how do you react? More importantly, how do you prevent this from happening again?

Here’s the thing: I don’t blame the engineer. I think it’s a fundamental problem that stems from the way we’re brought up, and more broadly, from Western-based education systems.

Think about it like this:

  • As a child, you have your parents telling you what to do.
  • In school, your teachers tell you what to do.
  • At university, your lecturers tell you what to do.

You spend the first part of your life with people telling you what to do. So it’s only natural that people find it easy to get trapped into finding the next person to tell them what to do. And usually, in dev teams that do Scrum, this becomes their Product Owner or manager.

It’s the managers responsibility to coach this out of people.

The Real Costs

This way of working comes with significant costs:

  1. Strategic Misalignment: Your team’s efforts aren’t driving towards key business objectives. You’re busy, but are you moving in the right direction?
  2. Opportunity Cost: Time spent on unnecessary features or misguided efforts is time not spent on innovations that could provide a real competitive advantage.
  3. Talent Retention Risk: Skilled developers often leave when they feel their work lacks purpose or impact. Are you at risk of losing your best people?

Solutions: Leadership for Purpose-Driven Development

As a leader, you have the power to shift your team’s focus from output to outcomes. Here’s how:

  1. Reinforce the ‘Why’: Push your engineers to ask why. Why are we building this feature? Why is it important? Why now?
  2. Redefine Success Metrics: Your Product Manager should already be doing this, but they might be hiding it from the engineers, I’ve seen this many times, some Product people think by doing this it’s less distracting for the engineers, but it has a negative effect. If they’re not doing it at all, you have bigger problems, and you probably need to go higher than your team to address them.
  3. Encourage Customer Connection: Break down the barriers between your developers and the users they’re building for. Teach them who they serve, the customer, and if you can introduce them to some and get them talking to them.
  4. Promote Learning Loops: Make time to analyze the impact of your work after it’s shipped. What worked? What didn’t? Why? Get your engineers engaged with the Analytics data that comes out of their system, get them excited about how many users are using their new feature, and if people aren’t, ask why?
  5. Cross-Team Collaboration: And I don’t just mean in formal settings. Have a beer together sometimes. Build real relationships across teams, Engineers, Design, Product and other business units.

Understanding the “Feature Factory” Phrase

The term “feature factory” vividly illustrates a development process that prioritizes output over outcomes, quantity over quality. Like workers on an assembly line, developers in this environment might be busy but disconnected from the larger purpose of their work.

As a leader, your role is to transform this factory into an innovation studio – a place where each line of code contributes to a larger vision, where your team’s skills are applied to solving real problems, not just checking off feature lists.

Moving Forward

Recognizing that your team may be stuck in this output-focused mindset is a crucial first step. The next is to start changing the conversation at all levels – with your team, with product managers, with stakeholders.

Start asking different questions in your meetings:

  • “How will we measure the success of this feature?”
  • “What problem are we solving for our users?”
  • “If this feature succeeds, what impact will it have on our key business metrics?”

Encourage your team to think beyond the immediate task to the larger purpose. Help them see their work not as isolated features, but as integral parts of a solution that brings real value to users and the business.

Remember, you became a leader to make a difference – to guide your team to create impactful, meaningful work. Don’t let the trap of focusing on output rob you and your team of that opportunity.

Are you ready to lead the change? Your team’s potential for true innovation and impact is waiting to be unleashed.

Measuring Product Health: Beyond Code Quality

In the world of software development, we often focus on code quality as the primary measure of a product’s health. While clean, efficient code with passing tests is crucial, it’s not the only factor that determines the success of a product. As a product engineer, it’s essential to look beyond the code and understand how to measure the overall health of your product. In this post, we’ll explore some key metrics and philosophies that can help you gain a more comprehensive view of your product’s performance and impact.

The “You Build It, You Run It” Philosophy

Before diving into specific metrics, it’s important to understand the philosophy that underpins effective product health measurement. We follow the principle of “You Build It, You Run It.” This approach empowers developers to take ownership of their products not just during development, but also in production. It creates a sense of responsibility and encourages a deeper understanding of how the product performs in real-world conditions.

What Can We Monitor?

When it comes to monitoring product health, there are several areas we usually focus on:

  1. Logs: Application, web server, and system logs
  2. Metrics: Performance indicators and user actions
  3. Application Events: State changes within the application

While all these are important, it’s crucial to understand the difference between logs and metrics, and when to use each.

The Top-Down View: What Does Your Application Do?

One of the most important questions to ask when measuring product health is: “What does my application do?” This top-down approach helps you focus on the core purpose of your product and how it delivers value to users. So ultimatelly when this value is impacted you know when to act.

Example: E-commerce Website

Let’s consider an e-commerce website. At its core, the primary function of such a site is to facilitate orders. That’s the ultimate goal – to guide users through the funnel to complete a purchase.

So, how do we use this for monitoring? We ask two key questions:

  1. Is the application successfully processing orders?
  2. How often should it be processing orders, and is it meeting that frequency right now?

How to Apply This?

To monitor this effectively, we generally look at 10-minute windows throughout the day (for example, 8:00 to 8:10 AM). For each window, we calculate the average number of orders for that same time slot on the same day of the week over the past four weeks. If the current number falls below this average, it triggers an alert.

This approach is more nuanced and effective than setting static thresholds. It naturally adapts to the ebb and flow of traffic throughout the day and week, reducing false alarms while still catching significant drops in performance. By using dynamic thresholds based on historical data, you’re less likely to get false positives during normally slow periods, yet you remain sensitive enough to catch meaningful declines in performance.

One of the key advantages of this method is that it avoids the pitfalls of static thresholds. With static thresholds, you often face a dangerous compromise. To avoid constant alerts during off-hours or naturally slow periods, you might set the threshold very low. However, this means you risk missing important issues during busier times. Our dynamic approach solves this problem by adjusting expectations based on historical patterns.

While we typically use 10-minute windows, you can adjust this based on your needs. For systems with lower volume, you might use hourly or even daily windows. This will make you respond to problems more slowly in these cases, but you’ll still catch significant issues. The flexibility allows you to tailor the system to your specific product and business needs.

Another Example: Help Desk Chat System

Let’s apply our core question – “What does this system DO?” – to a different type of application: a help desk chat system. This question is crucial because it forces us to step back from the technical details and focus on the fundamental purpose of the system adn teh value it delviers to the business and ultimately the customer.

So, what does a help desk chat system do? At its most basic level, it allows communication between support staff and customers. But let’s break that down further:

  1. It enables sending messages
  2. It displays these messages to the participants
  3. It presents a list of ongoing conversations

Now, you might be tempted to say that sending messages is the primary function, and you’d be partly right. But remember, we’re thinking about what the system DOES, not just how it does it.

With this in mind, how might we monitor the health of such a system? While tracking successful message sends is important, it might not tell the whole story, especially if message volume is low. We should also consider monitoring:

  • Successful page loads for the conversation list (Are users able to see their ongoing chats?)
  • Successful loads of the message window (Can users access the core chat interface?)
  • Successful resolution rate (Are chats leading to solved problems?)

By expanding our monitoring beyond just message sending, we get a more comprehensive view of whether the system is truly doing what it’s meant to do: helping customers solve their problems efficiently.

This example illustrates why it’s so important to always start with the question, “What does this system DO?” It guides us towards monitoring metrics that truly reflect the health and effectiveness of our product, rather than just its technical performance.

A 200 Ok response, is not always OK

As you consider your own systems, always begin with this fundamental question. It will lead you to insights about what you should be measuring and how you can ensure your product is truly serving its purpose.

The Bottom-Up View: How Does Your Application Work?

While the top-down view focuses on the end result, the bottom-up approach looks at the internal workings of your application. This includes metrics such as:

  • HTTP requests (response time, response code)
  • Database calls (response time, success rate)

Modern systems often collect these metrics through contactless telemetry, reducing the need for custom instrumentation.

Prioritizing Alerts: When to Wake Someone Up at 3 AM

A critical aspect of product health monitoring is knowing when to escalate issues. Ask yourself: Should the Network Operations Center (NOC) call you at 3 AM if a server has 100% CPU usage?

The answer is no – not if there’s no business impact. If your core business functions (like processing orders) are unaffected, it’s better to wait until the next day to address the issue.

Using Loss as a Currency for Prioritization

Once you’ve established a health metric for your system and can compare current performance against your 4-week average, you gain a powerful tool: the ability to quantify “loss” during a production incident. This concept of loss can become a valuable currency in your decision-making process, especially when it comes to prioritizing issues and allocating resources.

Imagine your e-commerce platform typically processes 1000 orders per hour during a specific time window, based on your 4-week average. During an incident, this drops to 600 orders. You can now quantify your loss: 400 orders per hour. If you know your average order value, you can even translate this into a monetary figure. This quantification of loss becomes your currency for making critical decisions.

With this loss quantified, you can now make more informed decisions about which issues to address first. This is where the concept of “loss as a currency” really comes into play. You can compare the impact of multiple ongoing issues, justify allocating more resources to high-impact problems, and make data-driven decisions about when it’s worth waking up engineers in the middle of the night.

Reid Hoffman, co-founder of LinkedIn, once said, “You won’t always know which fire to stamp out first. And if you try to put out every fire at once, you’ll only burn yourself out. That’s why entrepreneurs have to learn to let fires burn—and sometimes even very large fires.” This wisdom applies perfectly to our concept of using loss as a currency. Sometimes, you have to ask not which fire you should put out, but which fires you can afford to let burn. Your loss metric gives you a clear way to make these tough decisions.

This approach extends beyond just immediate incident response. You can use it to prioritize your backlog, make architectural decisions, or even guide your product roadmap. When you propose investments in system improvements or additional resources, you can now back these proposals with clear figures showing the potential loss you’re trying to mitigate, all be it with a pitch of crytal ball about how likely these incident are to occura gain sometimes.

By always thinking in terms of potential loss (or gain), you ensure that your team’s efforts are always aligned with what truly matters for your business and your users. You create a direct link between your technical decisions and your business outcomes, ensuring that every action you take is driving towards real, measurable impact.

Remember, the goal isn’t just to have systems that run smoothly from a technical perspective. It’s to have products that consistently deliver value to your users and meet your business objectives. Using loss as a currency helps you maintain this focus, even in the heat of incident response or the complexity of long-term planning.

In the end, this approach transforms the abstract concept of system health into a tangible, quantifiable metric that directly ties to your business’s bottom line.

Conclusion: A New Perspective on Product Health

As we’ve explored throughout this post, measuring product health goes far beyond monitoring code quality or individual system metrics. It requires a holistic approach that starts with a fundamental question: “What does our system DO?” This simple yet powerful query guides us toward understanding the true purpose of our products and how they deliver value to users.

By focusing on core business metrics that reflect this purpose, we can create dynamic monitoring systems that adapt to the natural ebbs and flows of our product usage. This approach, looking at performance in time windows compared to 4-week averages, allows us to catch significant issues without being overwhelmed by false alarms during slow periods.

Perhaps most importantly, we’ve introduced the concept of using “loss” as a currency for prioritization. This approach transforms abstract technical issues into tangible business impacts, allowing us to make informed decisions about where to focus our efforts. As Reid Hoffman wisely noted, we can’t put out every fire at once – we must learn which ones we can let burn. By quantifying the loss associated with each issue, we gain a powerful tool for making these crucial decisions.

This loss-as-currency mindset extends beyond incident response. It can guide our product roadmaps, inform our architectural decisions, and help us justify investments in system improvements. It creates a direct link between our technical work and our business outcomes, ensuring that every action we take drives towards real, measurable impact.

Remember, the ultimate goal isn’t just to have systems that run smoothly from a technical perspective. It’s to have products that consistently deliver value to our users and meet our business objectives.

As you apply these principles to your own systems, always start with that core question: “What does this system DO?” Let the answer guide your metrics, your monitoring, and your decision-making. In doing so, you’ll not only improve your product’s health but also ensure that your engineering efforts are always aligned with what truly matters for your business and your users.

Finishing Strong: Completing Your Monolith Split

In our previous posts, we discussed identifying business domains in your monolith, planning the split, and strategies for execution. Now, let’s focus on the crucial final phase: finishing the split and ensuring long-term success.

Maintaining Momentum

As you progress through your monolith splitting journey, it’s essential to keep the momentum going.

Bi-weekly Check-ins or just having a regular cadence where you track progress to completion helps co-ordinate, especially if you have many teams working on it. Use these bi-weekly meetings to:

  1. Track progress towards completion
  2. Share wins and learnings across teams
  3. Identify and address blockers quickly
  4. Maintain visibility of the project at a management level

These regular touchpoints help ensure that the split remains a priority and doesn’t get sidelined by other initiatives.

Have a Plan to Finish

One of the most critical aspects of a successful monolith split is having a clear plan to finish. Without this, you’ll start another migration before you’ve finished this one and end up with a multi-generation codebase.

Have a timeline in your bi-weekly’s, update it as you go so everyone has their eyes on teh finish line.

This timeline should:

  1. Be realistic based on your progress so far
  2. Include major milestones and dependencies
  3. Be visible to all stakeholders

Remember, if you don’t finish, you’ll start another migration before you’ve finished this one and end up with a multi-generation codebase, which will explode cognitive load and lead to escaping bugs, war rooms, and prod incidents.

Handling the Long Tail

As you approach the end of your split, you’ll likely encounter a long tail of less-frequently used features or challenging components. Keep on top of them, it’ll be hard, but worth it in the end.

Celebrate the success at the end too, mark those big milestones, it means a lot to the people that worked tirelessly on the legacy code.

Conclusion

Completing a monolith split is a significant achievement that requires persistence, strategic thinking, and a clear plan. By maintaining momentum through regular check-ins, having a solid plan to finish, and consistently measuring your progress and impact, you can successfully navigate the challenges of this complex process.

Remember, the goal isn’t just to split your monolith—it’s to improve your system’s overall health, development velocity, and maintainability. Keep this end goal in mind as you make decisions throughout the process.

As you finish your split, take time to celebrate your achievement and reflect on the learnings. These insights will be invaluable for future architectural decisions and potential migrations.

Thank you for following this series on monolith splitting. We hope these insights help you navigate your own journey from monolith to microservices. Good luck with your splitting efforts!

Identifying and Planning Your Monolith Split

In the world of software development, monolithic architectures often become unwieldy as applications grow in complexity and scale. Splitting a monolith into smaller, more manageable services can improve development velocity, scalability, and maintainability. However, this process requires careful planning and execution. In this post, we’ll explore the crucial first steps in splitting your monolith: identifying business domains and creating a solid plan.

Finding Business Domains in Your Monolith

The first step in splitting a monolith is identifying the business domains within your application. Business domains are typically where “units of work” are isolated, representing distinct areas of functionality or responsibility within your system.

Splitting by business domain allows you to optimize for the majority of your units of work being in the one system. While you may never achieve 100% optimization without significant effort, focusing on business domains usually covers 80-90% of your needs.

How to Identify Business Domains

  1. Analyze Work Units: Look at the different areas of functionality in your application. What are the main features or services you provide?
  2. Examine Data Flow: Consider how data moves through your system. Are there natural boundaries where data is transformed or handed off?
  3. Review Team Structure: Often, team organization reflects business domains. How are your development teams structured?
  4. Consider User Journeys: Map out the different paths users take through your application. These often align with business domains.

For more detail here is a great book on the topic.

When to Keep Domains Together

Sometimes, you’ll find two domains that share a significant amount of code. In these cases, it might be more efficient to keep them in the same system. Consider creating a “modulith” (a modular monolith) or even maintaining a smaller monolith for these tightly coupled domains might make sense, but this is usually the exception to the rule, dont let it be an easy way out for you.

Analyzing Changes in the Monolith

Once you’ve identified potential business domains, the next step is to analyze how your monolith changes over time. This analysis helps prioritize which parts of the system to split first. Because this is where the value is, velocity, the more daily/weekly merge requests that happen in the new systems the more business impact you cause, and that’s our goal, business impact, in this case in the form of engineering velocity, don’t lose sight on this goal for some milestone driven Gantt chart.

There’s many elegant tools on the market for analysis for git and changes over time, I would encourage you to explore. We didn’t find any that worked for us because the domains were scattered throughout the code due to the age and size of our monolith (i.e. it was ancient).

What we found worked best, we used a hammer, its manual but it worked:

  1. Use MR (Merge Request) Labels: Implement a system where developers label each MR with the relevant business domain. This provides ongoing data about which domains of the system change most frequently.
  2. Add CI Checks: Include a CI step that fails if an MR doesn’t have a domain label. This ensures consistent data collection.
  3. Historical Analysis: Have your teams go through 1-2 quarters of historical MRs and label them retrospectively. This gives you an initial dataset to work with.

Once you have this data, wether it comes from the hammer approach or you find a more elegant one you want to look for patterns in your MRs. Which domains see the most frequent changes? This is how you prioritize your split.

Making a Plan

With your business domains identified and change patterns analyzed, it’s time to create a plan for splitting your monolith. Start with the domains that have the highest impact. These are the ones that change frequently.

Implement L7 Routing for incremental migration

Use Layer 7 (application layer) routing to perform A/B testing between your old monolith and new services. This allows you to:

  • Gradually shift traffic to new services
  • Compare performance and functionality potentially with AB Tests
  • Quickly roll back if issues arise

For Web Applications:

  • Consider migrating one page at a time
  • Treat each “page” as a unit of migration

Within pages sometimes we found that doing a staged approach with ajax endpoints individually helped to do the change more incrementally, but don’t let a “page” exist in multiple system for too long, it kills local dev experience, you go backwards on what you planned, you are meant to be improving dev experience, not making it worse, so finish it asap.

For Backend Services:

  • Migrate one endpoint or a small group of tightly coupled endpoints at a time
  • This allows for a gradual transition without disrupting the entire system

Also as you are incrementally migrating, if you focus is on fast killing the monolith, don’t bother deleting the old code as you go, let the thing die as a whole. This will give you more time to spend on moving to new systems. Try to not improve the experience on the old monolith, the harder it is to work on it the more likely a team is to make a decision to break something out of it, you increase the ROI this way of splitting.

Conclusion

Splitting a monolith is a significant undertaking, but with proper planning and analysis, it can lead to a more maintainable and scalable system. By identifying your business domains, analyzing change patterns, and creating a solid migration plan, you set the foundation for a successful transition from a monolithic to a microservices architecture.

In our next post, we’ll dive deeper into the strategies for executing your monolith split, including modularization techniques and how to handle ongoing development during the transition. Stay tuned!

The Pitfalls and Potential of Monolithic Architectures

Before we dive into the process of splitting a monolith, it’s crucial to understand why monoliths can become problematic and when they might still be a good choice. In this post, we’ll explore the challenges that often arise with monolithic architectures and discuss scenarios where they might still be appropriate.

What’s So Bad About Monoliths?

Monolithic architectures, where all components of an application are interconnected and interdependent, can present several challenges as systems grow:

1. Development Feedback Loops

One of the most significant issues with large monoliths is the impact on development feedback loops:

  • Compilation Time: Large codebases often take a long time to compile, slowing down the development process.
  • Test Execution Time: With a vast number of tests, running the entire test suite can be time-consuming.
  • Test Flakiness: As the number of tests grows, the overall stability of the test suite can decrease dramatically. For example:
    • If each individual test has a 99% stability rate (which sounds good),
    • In a suite with 179 tests, the actual stability rate becomes 0.99^179 ≈ 17%
    • This means there’s only a 17% chance of all tests passing in a given run!

2. Increased Lead Time

The factors mentioned above contribute to increased lead time for new features or bug fixes:

  • Longer compile and test times slow down the development cycle.
  • Large monoliths often require more server resources, leading to longer deployment times.

3. Framework Upgrades

Upgrading frameworks or libraries in a monolith can be a massive undertaking. Changes often need to be applied across the entire system simultaneously. the more code you have the more potential breaking change you need to fix in one go, the you have a large MR, and with high volume of change you normally get in big repos, good luck getting it merged with all the merge conflicts 🙂

The Pitfalls and Potential of Monolithic Architectures

Are Monoliths Ever Good?

Despite these challenges, monoliths aren’t always bad. In fact, they can be an excellent choice in certain scenarios:

1. Startups and Small Projects

Many large companies started with small monolithic applications. When you’re small and trying to “take on the world,” a monolith can be the fastest way to get a product to market. It allows for rapid development and iteration in the early stages of a product. This approach enables startups to focus on validating their business ideas and gaining market traction without the added complexity of a distributed system.

2. Simple Applications

For applications with straightforward requirements and minimal complexity, a monolith might be the most straightforward and maintainable solution. In such cases, the simplicity of a monolithic architecture can lead to faster development cycles and easier debugging, as all components are in one place.

3. Teams New to Microservices

If your team doesn’t have experience with distributed systems, starting with a well-structured monolith can be a good learning experience before moving to microservices. This approach allows the team to focus on building features and understanding the domain, while gradually introducing concepts like modularity and service boundaries within the monolith. As the team and application grow, this experience can make a future transition to microservices smoother and more informed.

Best Practices for Starting Small

If you’re starting a new project and decide to go with a monolithic architecture, here are some best practices:

  1. Plan for Future Splitting: Design your monolith with clear boundaries between different functionalities, making future splits easier.
  2. Use Modular Design: Even within a monolith, use modular design principles to keep different parts of your application loosely coupled.
  3. Maintain Clean Architecture: Follow clean architecture principles to separate concerns and make your codebase more manageable.
  4. Monitor Growth: Keep an eye on your application’s size and complexity. Be prepared to start splitting when you notice development slowing down or when the benefits of splitting outweigh the costs.

Conclusion

While monoliths can present significant challenges as they grow, they’re not inherently bad. The key is understanding when a monolithic architecture is appropriate and when it’s time to consider splitting. By being aware of the potential pitfalls and planning for future growth, you can make informed decisions about your application’s architecture.

In the next post, we’ll dive into the process of identifying business domains within your monolith, which is the first step in planning a successful split.

Essential Skills for Product Engineers (Part 2): Mastering the Craft

In our previous post, we explored the first set of essential skills for product engineers, focusing on non-technical abilities that bridge the gap between engineering and business. Today, we’ll dive into the second part of our essential skills series, covering more technically-oriented skills that are crucial for success in product engineering.

Data Analysis and Metrics

In the world of product engineering, data reigns supreme. This skill empowers engineers to make informed decisions, measure the impact of their work, and continuously improve product performance.

Metrics Definition is the foundation of effective data analysis. It’s not enough to simply collect data; you need to know which metrics are most relevant to your product and how they align with broader business goals. This requires a deep understanding of both the product and the business model. For instance, a social media application might focus on Daily Active Users (DAU) as a key engagement metric, along with other user interaction metrics like posts per user or time spent in the app. On the other hand, an e-commerce platform might prioritize conversion rates, average order value, and customer lifetime value. By defining the right metrics, engineers ensure that they’re measuring what truly matters for their product’s success.

The next step is Data Collection. This involves implementing systems to gather data accurately and consistently. It’s not just about collecting data, but ensuring its accuracy and integrity. Many engineers work with established analytics tools like Google or Adobe Analytics, which provide a wealth of user behavior data out of the box. However, for more specific or granular data needs, custom tracking solutions are necessary. This could involve instrumenting your code to log specific events or user actions. The key is to create a comprehensive data collection system that captures all the information needed to calculate your defined metrics.

With data in hand, the next skill is Statistical Analysis. While engineers don’t need to be statisticians, a basic understanding of statistical concepts is needed for interpreting data correctly. This includes grasping concepts like statistical significance, which helps determine whether observed differences in metrics are meaningful or just random noise. Understanding the difference between correlation and causation is also vital – just because two metrics move together doesn’t necessarily mean one causes the other. Handling outliers is another important skill, as extreme data points can significantly skew results if not treated properly. These statistical skills allow engineers to draw accurate conclusions from their data and avoid common pitfalls in data interpretation.

Data Visualization is where numbers transform into narratives. The ability to present data in clear, compelling ways is crucial for communicating insights to stakeholders who may not have a deep technical background. Tools like metabase, superset, grafana, etc offer powerful capabilities for creating interactive visualizations, while even simple Excel charts can be effective too. The goal is to make the data tell a story – to highlight trends, comparisons, or anomalies in a way that’s immediately understandable. Good data visualization can turn complex datasets into actionable insights, influencing product decisions and strategy.

A/B Testing is a technique in the engineer’s toolkit. It involves designing and implementing experiments to test hypotheses and measure the impact of changes. This could be as simple as testing two different button colors (one the A variant, the other the B) to see which drives more clicks, or as complex as rolling out a major feature to a subset of users to evaluate its impact on key metrics. Effective A/B testing requires understanding concepts like control groups (users who don’t receive the change), variable isolation (ensuring you’re testing only one thing at a time), and statistical power (having a large enough sample size to draw meaningful conclusions). Mastering A/B testing allows engineering teams to make data-driven decisions about feature development and optimization.

Performance Optimization

In today’s fast-paced digital world, user expectations for application performance have never been higher. Users demand fast, responsive applications that work seamlessly across devices and network conditions. As a result, performance optimization has become a critical skill for engineers. It’s not just about making things fast; it’s about creating a smooth, responsive user experience that keeps users engaged and satisfied, regardless of the complexity behind the scenes.

Profiling and Benchmarking form the foundation of effective performance optimization. Before you can improve performance, you need to understand where the bottlenecks are. This involves using a variety of tools to analyze your application’s performance characteristics. For front-end performance, browser developer tools provide powerful capabilities for analyzing load times, JavaScript execution, and rendering performance, chrome debugger and extensions allow testing stats like LCP, CLS, etc and debugging why they are bad locally, but don’t forget to measure RUM (Real User Metrics), getting data from your real user interactions. These tools can help identify slow-loading resources, long-running scripts, or inefficient DOM manipulations that might be causing performance issues.

On the backend, specialized profiling tools can help identify performance bottlenecks in server-side code or database queries. These tools like pyroscope, application insights and open telemetry tracing, might analyze CPU usage, memory allocation, or database query execution times to pinpoint areas for improvement. The key is to establish baseline performance metrics and then systematically identify the areas that have the biggest impact on overall application performance.

Once you’ve identified performance bottlenecks, the next step is applying Optimization Techniques. This is a topic for another post for sure, based on your environment this can vary greatly so I wont go into too much details today.

Google’s Core Web Vitals initiative is a prime example of the industry’s focus on performance and its impact on user experience. These metrics – Largest Contentful Paint (LCP), First Input Delay (FID), and Cumulative Layout Shift (CLS) – provide a standardized way to measure key aspects of user-centric performance. LCP measures loading performance, FID measures interactivity, and CLS measures visual stability. By focusing on these metrics, engineers can ensure they’re optimizing for the aspects of performance that most directly impact user experience.

For example, optimizing for Largest Contentful Paint might involve prioritizing the loading of above-the-fold content, while improving First Input Delay could involve breaking up long tasks in JavaScript to improve responsiveness to user interactions. Minimizing Cumulative Layout Shift often involves careful management of how content loads and is displayed, ensuring that elements don’t unexpectedly move around as the page loads.

The importance of these metrics extends beyond just providing a better user experience. Search engines like Google now consider these performance metrics as ranking factors, directly tying performance optimization to an application’s visibility and success.

Security and Privacy

Cyber threats are ever-evolving and privacy regulations are becoming increasingly stringent, security and privacy considerations must be at the forefront of a engineer’s mind. These are not just technical challenges, but fundamental aspects of building user trust and ensuring the long-term success of a product.

Threat Modeling is a proactive approach to security that involves anticipating and modeling potential security threats to your application. This process requires engineers to think like attackers, identifying potential vulnerabilities and attack vectors in their systems. It’s not just about considering obvious threats like unauthorized access, but also more subtle risks like data leakage or denial of service attacks. Effective threat modeling involves mapping out the system architecture, identifying assets that need protection, and systematically analyzing how these assets could be compromised. This process should be an ongoing part of the development lifecycle, revisited as new features are added or the system architecture evolves.

Secure Coding Practices are the foundation of building secure applications. This involves understanding and implementing best practices for writing code that is resistant to common security vulnerabilities. Input validation is a crucial aspect of this, ensuring that all data entering the system is properly sanitized to prevent attacks like SQL injection or cross-site scripting. Proper authentication and authorization mechanisms are essential to ensure that users can only access the resources they’re entitled to. Secure data storage practices, including proper encryption of sensitive data both at rest and in transit, are also critical. Engineers should be familiar with common security vulnerabilities (like those listed in the OWASP Top 10) and know how to mitigate them in their code.

Compliance Understanding has become increasingly important as privacy regulations have proliferated around the world. Engineers need at least a basic understanding of relevant privacy regulations like the General Data Protection Regulation (GDPR) in Europe or the California Consumer Privacy Act (CCPA) in the United States. This doesn’t mean engineers need to become legal experts, but they should understand how these regulations impact product development. For example, GDPR’s “right to be forgotten” requirement has implications for how user data is stored and managed. Understanding these regulations helps engineers make informed decisions about data handling and storage, and ensures that privacy considerations are factored into product design from the outset.

Security Testing is a important skill for ensuring that the security measures implemented are effective. This involves familiarity with various security testing tools and practices. Penetration testing, or “pen testing,” involves simulating attacks on a system to identify vulnerabilities. This can be done manually by security experts or using automated tools. Code security scanners are another important tool, analyzing code for potential security issues. Static Application Security Testing (SAST) tools can identify vulnerabilities in source code, while Dynamic Application Security Testing (DAST) tools can find issues in running applications. Engineers should be familiar with these tools and be able to interpret and act on their results.

Security and privacy are no longer optional considerations in engineering – they are fundamental requirements. As cyber threats continue to evolve and users become increasingly aware of privacy issues, the ability to build secure, privacy-respecting products will be a key differentiator for engineers.

Scalability and Reliability

As products grow and user bases expand, the ability to scale systems to meet increased demand while maintaining reliability becomes an important skill for engineers. This is not just about handling more users or data; it’s about ensuring that the product continues to perform well and provide a consistent user experience even as it grows exponentially.

Distributed systems involve multiple components working together across different networks or geographic locations to appear as a single, cohesive system to end-users. This approach allows for greater scalability and fault tolerance, but it also introduces complexities in areas like data consistency, network partitions, and system coordination. Engineers need to understand concepts like CAP theorem, and it’s proponents. They should be familiar with patterns like microservices architecture, moduliths, event sourcing, etc. and how these apply with scale.

Load Balancing and Caching are critical strategies for managing increased demand on systems. Load balancing has changed greatly in recent years, gone are teh days of a large “in front everywhere” infrastructure, in favour of load balancing sidecars now with tech like envoy, and in-front load balancing banished to the edges. Engineers should be familiar with different load balancing algorithms (like round-robin, least connections, etc.) and understand when to use each as well as how health checks work in these scenarios.

Caching, on the other hand, could involve in-memory caches like Redis, content delivery networks (CDNs) for static assets, or application-level caching strategies. Effective caching requires careful consideration of cache invalidation strategies to ensure users always see up-to-date information. Engineers should understand not only pull through cache but other forms such as write-through, etc and also when to prewarm and expire based on the data and user needs.

Database Scaling is often one of the most challenging aspects of growing a system. As data volume and read/write operations increase, a single database instance may no longer be sufficient. Engineers need to be familiar with various database scaling techniques. Vertical scaling (adding more resources to a single machine) can work up to a point, but eventually, horizontal scaling becomes necessary and presents many challenges and options that engineers should be familiar with to be able to make the right choice.

Chaos Engineering is a proactive approach to ensuring system reliability that has gained prominence in recent years. The core idea is to intentionally introduce failures into your system in a controlled manner to test its resilience. This helps identify weaknesses in the system that might not be apparent under normal conditions.

Netflix’s Chaos Monkey is a prime example of this approach. This tool randomly terminates instances in their production environment, forcing engineers to build systems that can withstand these types of failures. By simulating failures in a controlled way, Netflix ensures that their systems can handle unexpected issues in real-world scenarios.

Other forms of chaos engineering might involve simulating network partitions, inducing latency, or exhausting system resources. The key is to start small, build confidence, and gradually increase the scope of these experiments. This approach not only improves system reliability but also builds a culture of resilience within engineering teams.

The importance of scalability and reliability in product engineering cannot be overstated. As users increasingly rely on digital products for critical aspects of their lives and work, the cost of downtime or poor performance can be enormous, both in terms of lost revenue and damaged user trust.

Moreover, the ability to scale efficiently can be a key competitive advantage. Products that can quickly adapt to growing demand can capture market share and outpace competitors. On the flip side, products that struggle with scalability often face user frustration, increased operational costs, and missed opportunities.

Continuous Integration and Deployment (CI/CD)

CI/CD practices enable teams to deliver code changes more frequently and reliably, accelerating the feedback loop and reducing the risk associated with deployments.

Engineers need to be proficient in writing effective, efficient tests and understanding concepts like test coverage and why the test pyramid is flawed, and new concepts like the testing honey combe. They should also be familiar with testing frameworks and tools specific to their technology stack. The goal is to catch bugs early in the development process, reducing the cost and risk of fixing issues in production.

Continuous Integration (CI) means continuously integrating code, its not about your Jenkins or github actions pipeline, its about fast merging changes together. Git branches are counter to this principle, but necessary in order to facilitate change in manageable or deployable chunks. Good Engineers understand CI is a principle, not a build system, this help them focus on it’s purpose which is moving fast an efficiently.

Continuous Deployment (CD) key skills here include understanding deployment strategies like blue-green deployments or canary releases, which minimize risk and downtime during updates. Engineers need to be proficient in infrastructure-as-code tools like Helm, Terraform or CloudFormation to manage their infrastructure alongside their application code. They should also be familiar with containerization technologies like Docker and orchestration platforms like Kubernetes, which can greatly simplify the process of deploying and scaling applications.

Feature Flags have become an essential tool in modern CD practices. They allow teams to decouple code deployment from feature release, giving more control over when and to whom new features are made available. Engineers need to understand how to implement feature flag systems, which can range from simple configuration files to more complex, dynamically controllable systems. This involves not just the technical implementation, but also understanding the strategic use of feature flags for A/B testing, gradual rollouts, and quick rollbacks in case of issues. Proper use of feature flags can significantly reduce the risk associated with deployments and allow for more frequent, smaller releases.

The benefits of mastering CI/CD are significant. It allows teams to deliver value to users more quickly, reduce the risk associated with each deployment, and spend less time on manual, error-prone deployment processes. It also improves developer productivity and satisfaction by providing quick feedback on code changes and reducing the stress associated with large, infrequent releases.

Cross-Platform Development

In today’s diverse technological landscape, users access digital products through a multitude of devices and platforms. As a result, the ability to develop cross-platform solutions has become an increasingly valuable skill for product engineers.

Responsive Web Design (RWD) forms the foundation of cross-platform web development. It’s an approach to web design that makes web pages render well on a variety of devices and window or screen sizes. The core principle of RWD is flexibility – layouts, images, and cascading style sheet media queries are used to create a fluid design that adapts to the user’s screen size and orientation. They should also understand the principles of mobile-first design, which advocates for designing for mobile devices first and then progressively enhancing the design for larger screens.

Cross-Platform Frameworks have emerged for native mobile development as a popular solution for building mobile apps that can run on multiple platforms with a single codebase. Tools like React Native, Flutter and even Web View allow developers to write code once and deploy it to both iOS and Android, potentially saving significant development time and resources.

Proficiency in cross-platform frameworks requires not just knowledge of the framework itself, but also an understanding of the underlying mobile platforms. Engineers need to know when to use platform-specific code for certain features and how to optimize performance for each platform.

The choice between these different approaches – responsive web, native apps, cross-platform frameworks, or even PWAs – depends on various factors including the target audience, required features, performance needs, and development resources. Engineers need to understand the trade-offs involved in each approach and be able to make informed decisions based on the specific requirements of each project.

Moreover, the field of cross-platform development is rapidly evolving. New tools and frameworks are constantly emerging, and existing ones are regularly updated with new features. For example, Flutter has expanded beyond mobile to support web and desktop platforms as well. React Native is used in the PS5 UI now expanding its reach to home entertainment.

This constant evolution means that cross-platform development skills require ongoing learning and adaptation. Engineers need to stay updated with the latest developments in this field, continuously evaluating new tools and approaches to determine if they can provide benefits for their projects.

Conclusion

These technical skills – data analysis, performance optimization, security and privacy, scalability and reliability, CI/CD, and cross-platform development – form the backbone of an engineer’s technical toolkit. Combined with the non-technical skills we discussed in our previous post, they enable engineers to build products that are not only technically sound but also user-friendly, scalable, and aligned with business goals.

Remember, the field of product engineering is constantly evolving. The most successful engineers are those who commit to lifelong learning, always staying curious and open to new technologies and methodologies.

What technical skills have you found most valuable in your product engineering journey? How do you stay updated with the latest trends and technologies? Share your experiences and tips in the comments below!

Essential Skills for Product Engineers (Part 1): Beyond the Code

In our previous posts, we’ve explored the evolution of product engineering, its core principles, and the mindset that defines successful product engineers. Now, let’s dive into the specific skills that product engineers need to thrive in their roles. This post, the first of two parts, will focus on four essential non-technical skills: goal setting and value targeting, decision making and risk assessment, understanding business models, and design thinking and empathy.

Goal Setting and Value Targeting

One of the most crucial skills for product engineers is the ability to set clear, meaningful goals and target value creation. This skill goes beyond simply meeting technical specifications or delivering features on time.

One of the hardest things about goal setting, is once you set a goal you set your conditions for failure, and no one like to fail, but this is part of the mindset we spoke about before, you need to be ok with failure, its a learning experience, you need to be ok with setting moonshot goals occasionally too.

Effective goal setting involves:

  1. Alignment with business objectives: Goals should directly contribute to the company’s overall strategy and key performance indicators (KPIs).
  2. User-centric focus: Goals should reflect improvements in user experience or solve specific user problems.
  3. Measurability: Goals need to be quantifiable, allowing for clear evaluation of success.
  4. Timebound nature: Setting realistic timelines helps maintain focus and urgency, and also set increments for fast feedback cycles

For example, instead of setting a goal like “Implement a new recommendation system,” an engineering team might frame it as “Increase user engagement by 20% within three months by implementing a personalized recommendation system.”

Value targeting involves identifying and prioritizing the work that will deliver the most significant impact. This requires a deep understanding of both user needs and business priorities. Engineering Teams must constantly ask themselves: “Is this the most valuable thing I could be working on right now?”

Decision Making and Risk Assessment

Product engineers often find themselves at the intersection of technical possibilities, user needs, and business constraints. In this complex environment, the ability to make effective decisions becomes a critical skill. It’s not just about choosing the best technical solution, but about finding the optimal balance between various competing factors.

One of the key aspects of decision making for engineers is adopting a data-driven approach. This involves utilizing both quantitative and qualitative data to inform decisions. Quantitative data might include metrics from A/B tests, performance benchmarks, or usage statistics. This hard data provides concrete evidence of how different options perform. However, it’s equally important to consider qualitative data, such as user feedback or expert opinions. These insights can provide context and nuance that numbers alone might miss. By combining both types of data, Engineers can make more holistic, well-informed decisions.

Another crucial aspect of decision making is the consideration of trade-offs. In the real world, there’s rarely a perfect solution that optimizes for everything. Instead, Engineers must navigate complex trade-offs. For example, they might need to balance the speed of development against the quality of the end product, or weigh short-term gains against long-term sustainability. The skill lies not just in recognizing these trade-offs, but in being able to evaluate them effectively. This often involves quantifying the potential impacts of different choices and making judgment calls based on the specific context of the project and the company’s overall strategy.

Reid Hoffman reflecting on his time at startups once said “Sometimes it’s not about deciding which fire you put out, its about deciding which ones you can let burn”, making trade offs can involve hard choices.

Stakeholder management is another key component of effective decision making. Engineers need to consider how their decisions will impact various stakeholders, from end-users to business teams to other engineering teams. This involves not just making the right decision, but also being able to communicate the rationale effectively. Engineers must be able to explain technical concepts to non-technical stakeholders, articulate the business impact of technical decisions, and build consensus around their chosen approach.

In traditional software development companies, they hire BAs to deal with the business and try to “shield” the engineers or Scrum masters to “keep the wolves at bay”, Product Engineering is about removing these layers, the engineers themselves have enough understanding that they can deal with the stakeholders and this make communication and decision making more effective.

Alongside decision making, risk assessment. In any project or initiative, there are always potential risks that could derail success. The ability to identify these risks, evaluate their potential impact, and develop mitigation strategies is vital.

Engineers need to be able to look at different technical approaches and understand their potential pitfalls. This might involve considering factors like scalability, maintainability, or compatibility with existing systems. It’s about looking beyond the immediate implementation and considering how a technical choice might play out in the long term.

Engineers also need to be able to assess business risks. This involves evaluating how technical decisions might impact business metrics or user satisfaction. For example, a technically elegant solution might be risky if it requires a steep learning curve for users, potentially impacting adoption rates.

Another important aspect of risk assessment is opportunity cost consideration. In the world of product development, choosing one path often means not pursuing others. Engineers need to recognize this and factor it into their decision making. This might involve considering not just the risks of a chosen approach, but also the potential missed opportunities from alternatives not pursued.

Google’s approach to “Moonshot Thinking” in their X development lab provides a great example of how to balance ambitious goals with thoughtful risk assessment. Engineers in this lab are encouraged to tackle huge problems and propose radical solutions – true “moonshots” that could revolutionize entire industries. However, this ambition is tempered with a pragmatic approach to identifying and mitigating risks. Engineers are expected to critically evaluate their ideas, identifying potential failure points and developing strategies to address them. This approach allows for bold innovation while still maintaining a realistic perspective on the challenges involved.

By developing strong skills in decision making and risk assessment, engineers can make choices that balance technical excellence with business needs and user expectations, while also managing potential risks and trade-offs. These skills are what separate great engineers from merely good ones, enabling them to drive real impact and innovation in their organizations.

Understanding Business Models

While product engineers are primarily focused on technical challenges, a solid understanding of business models has become increasingly important in today’s tech landscape. This knowledge isn’t about turning engineers into business experts, but rather about equipping them with the context they need to make decisions that align with the company’s strategy and contribute to its overall success. By understanding the business side of things, engineers can better prioritize their work, make more informed technical decisions on the spot with out escalating to get direction.

One of the key aspects of understanding business models is grasping how the company generates revenue. Revenue streams can vary widely depending on the nature of the business. Some companies rely on subscription models, where users pay a recurring fee for access to a product or service. Others may generate revenue through advertising, leveraging user attention to sell ad space. Transaction fees are another common revenue stream, particularly for e-commerce or financial technology companies. Some businesses may use a combination of these or have more unique revenue models. For engineers, understanding these revenue streams is crucial because it can inform decisions about feature development, user experience design, and system architecture. Especially around immediate systems they work on, they are able to easily related back work they are doing to impact on company bottom line.

Equally important is an understanding of cost structures. Every business has costs associated with delivering its product or service, and these can significantly impact the viability of different technical approaches. Common costs might include server infrastructure, data storage, customer support, etc. Product engineers need to be aware of how their technical decisions might impact these costs. For example, choosing a more complex architecture might increase development and maintenance costs, while optimizing for performance could reduce infrastructure costs, and conversely a negative performance impact or bug could lead to a escalation in support calls. By understanding the cost implications of their decisions, engineers can make choices that balance technical excellence with business sustainability.

Another crucial aspect of business models is understanding customer segments. Most products don’t serve a single, homogeneous user base, but rather cater to different groups of users with varying needs and behaviors. Engineers need to be aware of these different segments and how they interact with the product. This understanding can inform decisions about feature prioritization, user interface design, and even technical architecture. For instance, if a significant customer segment primarily uses the product on mobile devices, that might influence decisions about mobile optimization or the development of mobile-specific features.

Perhaps the most important element of a business model is the value proposition – the unique value that the company offers to its customers. This is what sets the company apart from its competitors and drives customer acquisition and retention. Engineers play a crucial role in delivering and enhancing this value proposition through the technical solutions they develop.

Let’s consider a concrete example to illustrate these concepts. Imagine you’re an engineer working at Spotify. Understanding Spotify’s business model would be crucial to your work. You’d need to know that Spotify operates on a freemium model, with both ad-supported free users and subscription-based premium users. This dual revenue stream (advertising and subscriptions) would inform many of your decisions.

For instance, when developing new features, you’d need to consider how they might impact the conversion rate from free to premium users. A feature that significantly enhances the listening experience might be reserved for premium users to drive subscriptions. On the other hand, a feature that increases engagement might be made available to all users to increase ad revenue from free users and make the platform more attractive to advertisers.

You’d also need to understand Spotify’s cost structure, particularly the significant costs associated with royalty payments to music rights holders. This might influence decisions about caching and data delivery to optimize streaming and reduce costs.

Understanding Spotify’s customer segments would be crucial too. You might need to consider the different needs of casual listeners, music enthusiasts, and artists using the platform. Each of these segments might require different features or optimizations.

Finally, you’d need to keep in mind Spotify’s value proposition of providing easy access to a vast library of music, personalized to each user’s tastes. Your technical decisions would need to support this, perhaps by focusing on recommendation algorithms, seamless playback, or features that enhance music discovery.

By understanding these aspects of Spotify’s business model, you as a engineer would be better equipped to make decisions that not only solve technical challenges but also drive the company’s success in a highly competitive market.

While engineers don’t need to become business experts, a solid grasp of business models is an increasingly valuable skill. It provides crucial context for technical decisions, helps in prioritizing work, and enables more effective collaboration with business stakeholders.

Design Thinking and Empathy

In the realm of product engineering, technical expertise alone is no longer sufficient to create truly impactful solutions. Enter design thinking: a problem-solving approach that places user needs and experiences at the center of the development process. For engineers, incorporating design thinking principles can lead to more innovative, user-friendly, and ultimately successful products.

Design thinking is not a linear process, but rather an iterative approach that encourages continuous learning and refinement. It typically involves five key elements, each of which plays a crucial role in developing user-centered solutions:

The first step is to Empathize. This involves deeply understanding the user’s needs, wants, and pain points. It’s about stepping into the user’s shoes, observing their behaviors, and listening to their experiences. For engineers, this might involve conducting user interviews, analyzing user data, or even spending time using the product as a user would. The goal is to uncover insights that may not be immediately apparent from technical specifications or feature requests.

Next comes the Define stage. Here, the insights gathered during the empathy stage are synthesized to clearly articulate the problem that needs to be solved. This is not about jumping to solutions, but about framing the problem in a way that opens up possibilities for innovative approaches. For engineers, this might involve reframing technical challenges in terms of user needs or business objectives.

The third stage is Ideation. This is where creativity comes to the forefront. The goal is to generate a wide range of possible solutions, without judgment or constraint. Techniques like brainstorming, mind mapping, or even role-playing can be used to spark new ideas. For engineers, this stage is an opportunity to think beyond conventional technical solutions and consider novel approaches that might better serve user needs.

Following ideation comes Prototyping. This involves creating quick, low-fidelity versions of potential solutions. The key here is speed and simplicity – the goal is not to build a perfect product, but to create something tangible that can be tested and refined. For engineers, this might involve creating basic wireframes, simple mock-ups, or even paper prototypes. The focus is on making ideas concrete enough to gather meaningful feedback.

The final stage is Testing. This is where prototypes are put in front of real users to gather feedback. It’s a critical stage that often leads back to earlier stages as new insights emerge. For engineers, this might involve conducting user testing sessions, analyzing usage data from beta releases, or going to a coffee shop and conducting guerilla testing session on patrons in exchange for buying them a coffee. The key is to approach this stage with an open mind, ready to learn and iterate based on user responses.

While all stages of design thinking are important, empathy deserves special attention as it forms the foundation of this approach. For engineers, developing empathy is about more than just understanding user requirements – it’s about truly connecting with the user’s experience.

User perspective is a crucial aspect of empathy. This involves the ability to see the product from the user’s point of view, understanding their context, motivations, and frustrations. It’s about asking questions like: What is the user trying to achieve? What obstacles do they face? How does our product fit into their broader life or work? By adopting the user’s perspective, engineers can make design and technical decisions that truly serve user needs, rather than just meeting specifications.

Diverse user consideration is another key aspect of empathy in product engineering. Users are not a monolithic group – they have diverse needs, abilities, and contexts. Some users might be tech-savvy early adopters, while others might be less comfortable with technology like your Aunty perhaps. Some might be using the product in resource-constrained environments, like low bandwidth internet in remote areas. Recognizing and considering this diversity in product development is crucial for creating truly inclusive and accessible products.

IDEO, the design company that popularized design thinking, emphasizes “human-centered design” as a cornerstone of their approach. Their methodology involves immersing themselves in the user’s world to gain deep, empathetic insights that drive innovation. This might involve spending time in users’ homes or workplaces, observing their behaviors and interactions with products in their natural environment. For engineers, adopting a similar approach – even if less intensive – can yield valuable insights that inform technical decisions and lead to more user-friendly solutions.

Design thinking can help engineers navigate the increasing complexity of modern product development. In a world where technical possibilities are vast and user expectations are high, design thinking provides a framework for focusing on what truly matters – creating solutions that make a meaningful difference in users’ lives.

Conclusion

These skills – goal setting and value targeting, decision making and risk assessment, understanding business models, and design thinking and empathy – form the foundation of a product engineer’s non-technical toolkit. They enable engineers to not just build products, but to create solutions that genuinely meet user needs and drive business success.

In our next post, we’ll explore the second set of essential skills for product engineers, including data analysis, A/B testing, and more. Stay tuned!

What’s your experience with these skills in your engineering work? How have you seen them impact product development? Share your thoughts and experiences in the comments below!

Understanding Product Engineering: A New Paradigm in Software Development

In our previous post, we explored how the software development landscape is rapidly changing and why traditional methods are becoming less effective. Today, we’re diving deep into the concept of product engineering – a paradigm shift that’s reshaping how we approach software development.

What is Product Engineering?

At its core, product engineering is a holistic approach to software development that combines technical expertise with a deep understanding of user needs and business goals. It’s not just about writing code or delivering features; it’s about creating products that solve real problems and provide tangible value to users.

Product engineering teams are cross-functional, typically including software engineers, designers, product managers, and sometimes data scientists or other specialists. These teams work collaboratively, with each member bringing their unique perspective to the table.

The Purpose of Product Engineering

1. Innovating on Behalf of the Customer

The primary purpose of product engineering is to innovate on behalf of the customer. This means going beyond simply fulfilling feature requests or specifications. Instead, product engineers strive to deeply understand the problems customers face and develop innovative solutions – sometimes before customers even realize they need them.

For example, when Amazon introduced 1-Click ordering in 1999, they weren’t responding to a specific customer request. Instead, they identified a pain point in the online shopping experience (the tedious checkout process) and innovated a solution that dramatically improved user experience.

2. Building Uncompromisingly High-Quality Products

Teams are committed to building high-quality products that customers love to use. This goes beyond just ensuring that the code works correctly. It encompasses:

  • Performance: Ensuring the product is fast and responsive
  • Reliability: Building systems that are stable and dependable
  • User Experience: Creating intuitive, enjoyable interfaces
  • Scalability: Designing systems that can grow with user demand

Take Spotify as an example. Their product engineering teams don’t just focus on adding new features. They continually work on improving streaming quality, reducing latency, and enhancing the user interface – all elements that contribute to a high-quality product that keeps users coming back.

3. Driving the Business

While product engineering is customer-centric, it also plays a crucial role in driving business success. Engineers need to understand the business model and how their work contributes to key performance indicators (KPIs).

For instance, at Agoda, a travel booking platform, teams might focus on metrics like “Incremental Bookings per Day” in the booking funnel or “Activations” in the Accommodation Supply side. These metrics directly tie to business success while also reflecting improvements in the customer experience.

Key Principles of Product Engineering

1. Problem-Solving Over Feature Building

Teams focus on solving problems rather than just building features. Instead of working from a list of specifications, they start with a problem statement. For example, rather than “Build feature X to specification Y,” a product engineering team might tackle “We don’t have a good enough conversion rate on our booking funnel.”

This approach allows for more creative solutions and ensures that the team’s efforts are always aligned with real user needs and business goals.

2. Cross-Functional Collaboration

Teams are enabled with all the expertise needed to solve the problem at hand. This might include UX designers, security experts, or even legacy system specialists, depending on the project’s needs.

This cross-functional collaboration ensures that all aspects of the product – from its technical architecture to its user interface – are considered from the start, leading to more cohesive and effective solutions.

3. Ownership of Results

Teams take ownership of the results, not just the delivery of features. If a change doesn’t increase conversion rates or solve the intended problem, it’s up to the team to iterate and improve until they achieve the desired results.

This shift from being judged on feature delivery to business results can be challenging for engineers used to traditional methods. As one engineer put it, “It was easier before when I just had to deliver 22 story points. Now you expect me to deliver business results?” However, this ownership leads to more impactful work and a deeper sense of satisfaction when real improvements are achieved.

The Shift from Feature Factories to Problem-Solving Teams

Traditional software development often operates like a “feature factory.” Requirements come in, code goes out, and success is measured by how many features are delivered to specification. This approach can lead to bloated software with features that aren’t used or don’t provide real value, remember our 37% unused software? that’s how companies get to this number.

Product engineering turns this model on its head. Teams are given problems to solve rather than features to build. They have the autonomy to explore different solutions, run experiments, and iterate based on real-world feedback. Success is measured not by features delivered, but by problems solved and value created for users and the business.

Conclusion

Product engineering represents a fundamental shift in how we approach software development. By focusing on customer needs, maintaining a commitment to quality, and aligning closely with business goals, teams are able to create software that truly makes a difference.

In our next post, we’ll explore the mindset required for successful product engineering. We’ll discuss the concept of T-shaped professionals and the balance of technical skills with business acumen that characterizes great product engineers.

What’s your experience with product engineering? Have you seen this approach in action in your organization? Share your thoughts and experiences in the comments below!

The Art of Managing Team Exits: Lessons for Engineering Leaders

As engineering leaders, we often focus on hiring, developing, and retaining talent. However, an equally important aspect of team management is handling exits – both voluntary and involuntary. How we manage these transitions can significantly impact our team’s morale, productivity, and long-term success. Let’s explore the dos and don’ts of managing team exits.

When Things Go South: Handling Involuntary Exits

People may forget many things about their job, but the day they’re let go is etched in their memory forever. Every minute of that day counts, so it’s crucial to handle these situations with utmost care and respect.

Show Leadership and Respect

As a leader, it’s your responsibility to handle difficult conversations directly. Don’t hide behind HR or the People Team. Show up, be present, and demonstrate genuine respect for the individual, regardless of the circumstances leading to their exit.

Consider the Ripple Effect

Remember, the exiting employee likely has social connections within your team. Whatever they experience during their exit process will be shared with their colleagues. If they leave feeling disrespected or unfairly treated, it can bring down the morale of your entire team.

Make the Best of a Bad Situation

While letting someone go is never pleasant, you can strive to make the process as respectful and supportive as possible. Offer guidance on next steps, provide honest and constructive feedback, and if appropriate, offer to serve as a reference for future opportunities.

For a deeper dive into handling these challenging situations, I highly recommend Ben Horowitz’s book, “The Hard Thing About Hard Things.” It offers valuable insights on navigating the toughest aspects of leadership. It’s mandatory reading for all my managers.

The Positive Approach: Planning for Voluntary Transitions

On the flip side, it’s important to recognize that people won’t (and shouldn’t) stay on your team forever. Variety in one’s career is healthy and contributes to personal and professional growth.

I was once in a meeting with a group of managers and HR about an engineer that resigned. And the person from HR was explaining the exit interview feedback they said “He said he left because he was on teh same team for 8 years, and nothing was changing”, his manager had missed this conversation with him in 1on1s, and we lost a good engineer, after that we got regular reports from HR about team tender to make sure we were addressing it. And as a Director I make a habit of pushing my managers to have conversation about how their directs are felling on the team, if they fell like a change, especially if they’ve been on the same team for 3-4 years.

If you have an engineer leave for another company to progress their career, it will send the wrong message to the other engineers on their team.

So plan for people to transition to other teams within your organization. Help them find roles that align with their future aspirations and development goals. This approach not only supports individual growth but also retains valuable talent within the company.

And for any engineer who’s been on your team for about three years, start having conversations about their future aspirations. Are they still finding the work challenging? Would they like to try something different? The exact timing may vary based on the individual and the nature of the work, but don’t let these conversations slide. In my experience, most people who’ve been in the same role for 8+ years are likely contemplating a significant change.

It’s far better to keep a good engineer within your organization, even if they move to a different team, than to lose them to another company. An internal move is usually less disruptive than an external exit. Moreover, you want to cultivate an environment where people feel they can grow their careers within the organization, rather than feeling they need to leave to progress.

Mark the Moment

Whether someone is moving to another team or leaving the company, always mark the moment with your team. Celebrate their contributions, share memories, and wish them well in their future endeavors at a team lunch or make an occasion somehow for this. This not only honors the departing team member but also reinforces a positive team culture.

Conclusion

Managing exits, whether voluntary or involuntary, is a crucial leadership skill. By handling these situations with respect, foresight, and empathy, you can maintain a positive team culture, support individual growth, and contribute to the overall health of your organization. Remember, how people leave your team is just as important as how they join it. Make every exit a testament to your leadership and your team’s values.

Mastering Execution in Engineering Teams: From Formation to Delivery

In the fast-paced world of software development, execution is everything. It’s not just about writing code; it’s about forming effective teams, collaborating across departments, focusing on outcomes, and managing technical debt. Let’s dive into these crucial aspects of engineering execution.

The Art of Forming Teams and Structures

When it comes to team formation, the old adage rings true: “Adding manpower to a late software project makes it later,” as famously stated in Brooks’ Law. This counterintuitive principle reminds us that team dynamics are complex and that simply adding more people doesn’t necessarily speed things up.

Understanding the stages of team formation is crucial. The Forming/Storming/Norming/Performing model, developed by Bruce Tuckman, provides a useful framework. In my experience, the Forming and Storming stages usually take a minimum of 2-3 sprints. If you’re struggling with these initial stages, consider reducing your sprint cadence to give the team a short reflection period on their working process to drive process change faster.

Here are some key principles for effective team structure:

Longevity should be a priority when structuring your engineering teams. Teams should be viewed as long-term investments rather than temporary assemblies. Even when headcount calculations don’t align perfectly, resist the urge to disband established teams. The relationships, shared knowledge, and mutual understanding that develop over time are invaluable assets that can’t be easily replicated. A team that has worked together for an extended period will often outperform a newly formed team, even if the latter looks better on paper.

Independence is another crucial factor in team effectiveness. Strive to create teams that possess all the skills necessary to execute their projects without constant handoffs to other teams. This autonomy not only boosts efficiency by reducing communication overhead and wait times but also increases accountability. When a team has end-to-end ownership of a project or feature, they’re more likely to take pride in their work and ensure its success.

Lastly, system ownership plays a vital role in team engagement and performance. In my experience, teams should have clear ownership over specific systems or components within your technology stack. This ownership fosters a deep understanding of the system and a sense of responsibility for its performance and evolution. Conversely, teams without any system ownership often struggle to appreciate impact of the technical debt they introduce and may lose respect for the value of the systems they interact with. By giving teams ownership, you’re not just assigning responsibility; you’re teaching a team about how to responsibly manage technical debt, as they are ultimately going to be then one’s responsible for it in their own system.

The Diplomacy of Inter-Team Collaboration

Working with other teams is an essential skill in any large organization, and it requires a strategic approach rooted in understanding human behavior and organizational dynamics. One crucial concept to keep in mind is what I like to call “Game Theory in Action.” When seeking collaboration with other teams, always consider the question, “What’s in it for me?” from their perspective. It’s a natural human tendency for individuals and groups to act in their own interest, and engineering teams are no exception. By anticipating this mindset, you can proactively address the needs and motivations of other teams, making collaboration more likely and more fruitful. This doesn’t mean being manipulative; rather, it’s about finding genuine win-win scenarios that benefit all parties involved.

Another key aspect of successful inter-team collaboration is the cultivation of informal networks within your organization. As a leader, one of your roles is to help your team build what I call an “irregular social network” that extends beyond the formal organizational structure. Encourage your team members to connect with colleagues from other departments, attend cross-functional meetings or events, and engage in casual conversations with people outside their immediate circle. These informal connections can be invaluable for smooth collaboration and problem-solving. They create channels for quick information exchange, foster mutual understanding, and often lead to creative solutions that might not emerge through formal channels alone. By building these networks, your team will be better positioned to know more about what’s going on within the org, and share more in common solutions to problems, in small organizations this isn’t as important as in large ones.

Shifting Focus: From Output to Outcome

It’s easy to get caught up in metrics like story points, sprint completion rates, or hours logged. However, these are merely measures of output, not outcome. Your true measure of success should be the business value your team delivers.

I once had a conversation with one of my engineers about changing the way the calculate carrier over work, I told him a half done story is “not done” and should count to zero for sprint completion, ultimately making their completion rate lower and closer to actual “completion”, his response was “But my points!”, he was fixated on his story points being his sole measure of success and was ignoring the actual value the team was delivering to the business.

Keep your engineers connected to the value they’re creating. Don’t let product management focus solely on “feature” or “milestone” success without tying it to measurable business value. If you do, you risk falling into the trap of DDD (Deadline Driven Development).

Remember Dan Pink’s insights on motivation: autonomy, mastery, and purpose are key drivers. By connecting your team’s work to real business outcomes, you’re providing that crucial sense of purpose.

Dan Pink, what motivates people

The Balancing Act of Technical Debt Management

Managing technical debt is a critical part of long-term success in software engineering, and it requires a strategic approach. One principle I’ve found effective is what I call the “30% Rule.” This involves allocating about 30% of your team’s time for technical improvements. While it might seem like a significant investment, especially when faced with pressing feature demands, this dedication to ongoing improvement pays substantial dividends in the long run. It helps prevent the accumulation of technical debt that can slow down development and increase the risk of system failures.

Why 30%? I asked Yaron Zeidman this once, who taught me this, and his response was, “Joel, I’ve worked in companies where we tried 20%, and we found that we weren’t able to keep on top of debt and technical improvements we needed, and i worked in companies where we tried 40%, and we found we weren’t able to execute on product enough, so 30% seems to be the happy middle ground.”.

Time-boxing is another powerful technique for addressing technical debt. One approach I’ve seen work well is the use of “Mobathons” – intensive periods focused solely on tackling technical debt or improvements. See this post about them.

Another instance, I once worked with a team that implemented a “60% leap sprint,” where the majority of a sprint was dedicated to making significant progress on technical debt, and every other sprint was 100% product work. These focused efforts can create momentum and visible progress, boosting team morale and improving system health.

If you try to do every sprint exactly 70/30 split, it almost never works out well.

One of the most important principles in managing technical debt is to finish what you start. It’s all too easy to let the tail end of technical migrations drag on for years, but this approach can be costly. The longer legacy systems remain in place, the more their costs grow, and the more significant their impact becomes. By seeing migrations through to completion, you can fully realize the benefits of your work and avoid the compounding costs of maintaining legacy systems.

When it comes to system design and development, thinking small can yield big benefits. Building small, modular systems allows for incremental improvement and quicker realization of value, for example framework upgrades such as reactjs or other frameworks, need to be done at system level, for a single large system it becomes an all in effort, if you have 10 smaller systems you can do one and measure the value in an increment, validate assumptions, to help you re-prioritize before continuing. This approach not only makes it easier to manage and update your systems but also allows for more frequent deliveries of value to your users and engineers.

While technical debt may seem like a purely engineering concern, it’s crucial to include product management in these discussions. Getting buy-in from product managers on your technical work can be tremendously beneficial. Not only can they help you ask the right questions about the business impact of technical decisions, but they can also become powerful allies in advocating for necessary technical work.

Finally, don’t hesitate to escalate when necessary. If technical debt is severely impacting your team’s ability to deliver, it’s time to have a serious conversation with product management and leadership. Work together to pitch for more headcount or resources. Remember, addressing technical debt isn’t just about engineering preferences – it’s about maintaining the health and efficiency of the systems that drive your business.

Conclusion

Effective execution in engineering teams is a multifaceted challenge. It requires thoughtful team formation, skilled inter-team collaboration, a focus on meaningful outcomes, and diligent technical debt management. By mastering these areas, you can create a high-performing engineering organization that consistently delivers value.

Remember, the goal isn’t just to write code or complete sprints. It’s to create systems and products that drive real business value. Keep this north star in mind, and you’ll be well on your way to engineering excellence.