When 10X Isn’t Good Enough
June 5, 2024, 13 min read time

Published by Souvik Sen in Engineering in AI

Ema’s Engineering Manifesto

Impact first.

As engineers, we must always understand how our work is creating customer impact. If you don’t understand the impact of your work, you are likely doing fake work. Don’t get stuck in doing fake work.

Examples of impactful work:

  • Building a product that has a tangible customer impact.
  • Building a demo that unlocks customer conversations
  • Building a test framework that dramatically increases how fast one can write tests at Ema
  • Reducing the number of steps and time required for developers to iterate on code, increasing developer velocity at Ema
  • Building a platform that increases the number of products/personas that can be built at Ema dramatically
  • Building an infrastructure that scales across availability, cloud, and reliability that unlocks a new customer base at Ema.

You are expected to own your work process end-to-end. Being blocked on other job functions isn’t an excuse. Roll up your sleeves, and figure out how to get it done. Remember, engineering is more than coding, product design is more than ideation, front-end development is more than styling and UX wiring.

Build an MVP and iterate to continue your incremental impact. Don’t obsess over engineering-purity concerns that won’t make a difference at our scale. Cut scope and make simplifying assumptions to get something working end-to-end; don’t block the whole product on one pet feature.

This does not mean…

…that only external-facing work is valuable. Your customer might be another engineer, another Ema employee in another function, or it might be the financial bottom line if you’re working on efficiency work. Regardless of the end goal, shipped impact is what matters.

…that engineering excellence, or thinking through work before doing it, isn’t valuable. Shipping doesn’t count if it’s not shipped well, because eventually, it will reduce our long-term impact. Shipping the same thing twice doesn’t count as twice the impact.

The only job title in Ema engineering is software engineer

We do not have separate roles for ML engineers. We do not have separate roles for QA. We do not have separate roles for front-end or back-end engineers. We do not have separate roles for database administrators, test engineers, or production automation engineers.

Everyone codes. Everyone understands systems at multiple levels of abstraction. We do not have strict silos. We do not have full-time experimenters or prompt engineers. We do not have architects who only design or coders who only code. It is not acceptable to refuse to do a task because you don’t know how or don’t want to — you can learn!

We do not have people-manager-exclusive roles. Engineering managers write code. They’re expected to do a slightly different set of activities, of course, but they are part of the engineering team first. Everyone is expected to contribute to product management and timeline planning, with managers as leaders and facilitators, not taking on that “softer” work all on their own.

This does not mean…

…that we don’t value specialized knowledge or past experience. Some of us have advanced degrees or training in ML; some of us have more experience in one part of the stack than others. Play to your strengths when possible, but you’ll be expected to branch out.

Ema engineers are all 10x engineers

10x engineering is a pattern of execution that can be learned and practiced. The most important thing is to be continuously productive and improving in one way or another.

Challenge the status quo: Don’t settle for normal goals. Look for ambitious engineering goals and pursue them with intense focus. Don’t just copy existing design patterns or code without understanding.

Keep yourself busy with multiple projects at once, so that you’re able to stay unblocked. Start and stagger multiple projects so that one is in the design phase while the second is in the execution phase. The variety will keep you from losing track of any part of the company, and different activities will operate on different cadences.

If you see a problem, solve it. Mediocre engineers wait for someone else to find problems, some others find the problems and just complain about it. 10x engineers find the problems, solve them, and move on without much fanfare.

Be frugal in design. Software bloats due to unnecessarily complicated designs that slow down performance or time to impact. Rejecting bloat means striving for simplicity and efficiency in software development. This involves making systems as simple and efficient as possible and reusing functions, modules, and APIs.

Think through your project end-to-end, and spot problems before they happen. The fastest work is work that doesn’t have to happen; the slowest work is work that has to be done twice. You’re an owner of the whole product, so getting your component done isn’t useful unless it contributes to the whole experience.

Use AI to gain leverage. We’re an AI-first company. Use AI when it’s useful, to automate tedious work, or to help form ideas. Learn how to use Copilot (every engineer has a license!), ChatGPT, etc. to their strengths to accelerate yourself when writing code.

Be your own QA. We will never have a separate Quality Assurance function in Engineering. Assuring the quality of our work, ensuring that we build is high quality, ensuring that our customers are successful, and ensuring that our product doesn’t regress is part of software engineering — testing, monitoring, and alerting. If you’re building something, your impact isn’t complete unless what you build works repeatedly and sustainably. You should personally make sure and take pride in the quality of what you build.

Use your team to ideate when you get stuck. No individual is a perfect output machine alone. Talk to your coworkers to help find information. Talk through your ideas to refine them.

This does not mean…

…that we have exactly the same expectations from every individual. Engineers with different levels of experience will scale differently. What we do expect is that every engineer will maximize their own efforts, and continually improve.

10x individuals aren’t good enough; we are a 10x team

Even if you’re a 10x engineer on your own, you can do better by scaling beyond yourself. Team performance matters more than your individual performance.

Share knowledge and expertise generously. Write documentation so that others can understand just as well as you do. Write design docs and comments that explain why you’ve done something, not just what you’ve done. Make sure everyone is on the same page. With precise documentation, you should be able to share your knowledge, while you sleep.

Enable your teammates. Be available to participate in design discussions. Respond promptly when your input is needed (but also, find ways to make yourself less personally necessary by sharing knowledge more widely!). Share your designs before you start executing so that others don’t work at cross-purposes.

Take the time to give and receive feedback. Write comments on design docs, and point out things you don’t understand. Read pull requests and give feedback from a place of understanding, don’t rubber-stamp.

Grow the team. Participate in interviewing and hiring, and keep the bar high. Help onboard, new engineers. Mentor and guide more junior engineers or anyone new to a problem or technical domain where you have a lot of experience.

This does not mean…

…that you aren’t still responsible for your own work. No engineer is purely an individual contributor or purely an enabler of others; all engineers should do a mix of both.

Tools serve humans, humans don’t serve tools

Machines exist to serve humans, not the other way around. If your developer tooling is bad, speak up. If the tool isn’t right or isn’t quite serving your purpose, fix it or extend it. If a tool doesn’t exist, write a new one. Software engineering is recursive, like being a blacksmith: the same skill that lets you use the tool is the skill that lets you improve it.

Processes exist to serve humans, not the other way around. If your team process isn’t making you more productive, speak up. If a meeting isn’t useful, find a better structure. If you find yourself doing busy work, talk to your manager and find a way to not do that.

Use automation wherever you can. Write automated tests. Write automated deployment. Write monitoring that will automatically tell you when things are broken. When manual human effort is unavoidable, write step-by-step playbooks or checklists so that we don’t have to rediscover how to do things.

This does not mean…

…that we won’t do things that don’t scale, especially in new product areas. Doing the scrappy manual thing once is an important part of staying productive and iterating quickly. Doing the scrappy manual thing twice is a problem.

…that everyone needs to, or should, build or select their engineering stack from scratch. While we expect everyone to contribute to improving our engineering stack, we also benefit from consistency.

Starting is half the work

We have an extreme bias toward action. Write code or sketch out an API to make the problem you’re grappling with concrete instead of the abstract. Solve real examples of problems, not hypotheticals.

Discover your assumptions, and test them. Build prototypes that will exercise the hard parts of the problem and prove that it’s possible to solve. There are no rules and boundaries at Ema. If you want to do something to create an impact, do it. Don’t wait.

Ideas are a dime a dozen, execution is all that matters. Don’t paint yourselves into a corner by starting a project with endless ideation and discussion. Don’t sit on writing a scoping, or design document for a week. Without appropriate validation, that’s a waste of your time. Build a prototype, quickly validate your hypothesis, and then write a design document to bring the knowledge together.

At our scale, most technical decisions are two-way streets. Make a decision, write the assumptions, and move on. Don’t wait on decision-making. Optionality is useful but don’t try to write a beautiful document with 10 options. If you really think that the decision is a one-way street (e.g., choosing a vendor), use the RAPID framework.

This does not mean…

…that thoughtful design isn’t important — quite the opposite. But getting to a useful, actionable design usually requires getting into the details first.

Finishing is the other half

Follow through and own your projects, including quality control. We do not have a separate quality control function; we have engineers, and we expect their output to be high quality. Communicate progress, and own the outcome.

Don’t leave things half-done or let work just trail off. Complete the project, or be honest enough with yourself and your teammates to cancel it. If something isn’t working, try to understand why, and document that too — negative results are still valuable.

Remember that your project is unfinished if you only have design, code, and unit tests. The rest of the software engineering process of automated end-to-end testing, monitoring, alerting, on-call runbooks, and good communication is equally as important.

Shipping the first version of the product does not mean you are done with the product. Remember, the customer’s product journey begins at that point. We still need to continuously monitor usage, quickly fix issues, and continuously improve the product to create enormous value for our customers.

Clean up after yourself. Remove dead code, close out experiments, and document the results. Detritus of past work makes every future project slower and harder to understand.

This does not mean…

… that we make perfect the enemy of good for MVP launches. At our stage, time to impact matters and MVP can be adequate for customer needs. Make sure to set expectations correctly with the customer and the GTM team working with the customer. Remember that our customers still expect high-quality products, but they may be constrained by the number of available features.