Engineering

Engineering Principles at Nextdoor

Written by #TeamNextdoor

At Nextdoor, the written version of these engineering principles are new; however, the principles themselves are not. These principles developed from within Nextdoor’s values, our purpose, how we’ve worked together over these last several years. Our goal in sharing these with the broader engineering community is so we can help learn from one another.

Engineers are constantly faced with weighing the advantages and disadvantages of various approaches and in many ways, it’s the art of making constant tradeoffs. Similar to other engineering organizations, Nextdoor has a set of unwritten rules on how to evaluate tradeoffs and to make strategic decisions. These principles were effectively embedded in the engineering culture and they spread verbally amongst our engineers over time.

As we rapidly scale Nextdoor’s engineering organization, we quickly realized it is important to explicitly write out these principles rather than leaving them unspoken. Moreover, unwritten rules cannot scale for a growing engineering organization distributed across multiple locations. Written rules are also more equitable as everyone has equal access to them. We want all new engineers to learn and apply our engineering principles quickly.

The goal for our new engineering principles is threefold. First, we want to create a shared vocabulary for how we weigh tradeoffs. Second, we wanted these principles to help us make consistent decisions all throughout the organization. Third, we wanted to create a shared understanding of the rules of engagement for how engineers and teams should interact with each other.

These principles are not meant to be dogmatic but rather to bias us towards a particular way of thinking. When engineers weigh the pros and cons of an approach, we think of these as a finger on the scale guiding us in a certain direction. Applying the principles requires exercising good judgment. In some cases, the principles may even be in tension with each other.

This post is very long, and that’s by design. As a company, Nextdoor has a small number of core values. We also have guiding principles that help us make day-to-day decisions. Each principle contains the description and also the rationale behind the principle. The reason for this is that these principles are often nuanced and we don’t want them being mindlessly applied as if they are hard-and-fast rules. It’s important to understand the intention behind the principle to know when and when not to apply it. In some cases, we explicitly call out the “limiting principle” to help us avoid over-indexing on these principles.

And if you are interested in building active local communities and are interested in our engineering principles, please reach out. We have multiple opportunities across all technical areas at Nextdoor. Please check our Careers Page out for a detailed list of all the roles currently open and let’s connect on Linkedin.

Purpose-Driven not Tech Driven

We’re a purpose-driven company. We never build technology for the sake of technology. We build technology to deliver value to the neighbors and organizations we serve. We build great infrastructure to enable our engineers to move faster. We use data and insights to understand how our changes impact our customers.

⭑ Recognize impact over shipping

In general, we bias towards recognizing sustainable impact over shipping. Impact is defined as delivering value to our neighborhoods and our customers (both internal and external). We strive not to “confuse movement with progress.” We strive to measure our impact with data when possible.

Why is this important? We want to align our engineers’ incentives with the company’s purpose.

Limiting Principle? Not every project we try will succeed. We will likely fail as much as we succeed. We never stigmatize failure, but we do expect that over the long term, the impact of our successes will outweigh the costs of our failures. See Optimize for Learning. In addition, at the more junior engineering levels, we do recognize and reward execution. Also, not every impactful change can be measured so sometimes the impact will be based on conviction, alignment with our product strategy, company values, and qualitative feedback.

When evaluating impact, we should always think about it as the impact-over-time summation (i.e. the integral under the curve). We don’t want to create a culture that rewards an engineer with achieving a modest short-term improvement at the expense of a large amount of tech debt that dramatically slows down future productivity. We should consider the impact holistically and take into account the short-term improvements with the long-term costs. This is heavily tied into our value of “Act Like an Owner” as an owner should always be considering value over a long-term time horizon.

⭑ Value over originality

We shouldn’t strive to be original for the sake of being original. Being different is not a goal. Being original is valuable when it’s in service of our purpose. In fact, much of what exists in our Engineering Principles is taken from the learnings of other companies.

Corollary. We don’t build when we can buy something or use open-source that meets our needs and building it doesn’t differentiate Nextdoor or the experience.

Limiting Principle? We shouldn’t blindly copy other technical and product decisions from other companies. We should always evaluate decisions in terms of Nextdoor’s purpose and values. We should understand that a decision made at a certain point of time does not necessarily mean it’s the right decision today.

⭑ Reward the foundational work

We celebrate and reward the foundational work that is critical to delivering value to our neighborhoods and to our customers. This work is equally as important and necessary as feature work. By foundational work, we mean all the work that goes into supporting a fast and polished product. This includes areas that provide leverage such as Infrastructure, Developer Experience, Platform APIs, and Tools. It also includes the work to maintain a clean codebase that we take pride in. It also includes the craftsmanship that goes into building a polished product that delivers delight to our neighborhoods.

Why is this important? Every type of work is important when it’s in service of our purpose. Fixing tech debt, supporting legacy systems, doing large painful refactorings, writing SQL queries to analyze an experiment are examples of this important work that we should all take on. Senior engineers should be models of this behavior. We should never think of a certain type of work as being dirty or unglamorous when it’s in service of our purpose.

⭑ Pragmatism over Dogmatism

As engineers, we are constantly faced with weighing tradeoffs and making recommendations and decisions. We hold opinions loosely in order to make pragmatic decisions based on known requirements. When conditions change, we let go of previously-held opinions. We bias towards making choices based on weighing the costs and benefits.

Limiting Principle? We don’t compromise on our company’s core values and we have created a set of guiding principles in this document to help us guide our behavior and decision-making process. That said, most decisions are rarely all or nothing and we are often tasked with evaluating tradeoffs when our principles or even core values may be in tension with each other.

⭑ Globally Optimize

We strive to make decisions that adhere to “What’s in Nextdoor’s best interest?” We are system-level thinkers and we take into account how our changes impact other teams in engineering, the entire company, our neighborhoods, and our customers.

Why is this important? Conway’s Law states that “Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.” By keeping this top of mind, we can resist shipping our org chart when it’s not serving our purpose.

Software Engineering is a Team Sport

We build software as teams, not as individuals. It’s essential that we are able to collaborate well with each other in order to reach the best outcomes.

⭑ We treat each other with respect

We are members of a community and it is essential that we treat each other with respect. We’re invested in one another’s success and this means we listen to each other and help each other to succeed. We understand that work is just one part of people’s lives and we seek to understand people in their entirety and withhold judgment.

Why is this important? Each engineer brings their unique superpowers, perspectives, and background to the table. We are only able to do our best work and harness our unique abilities when we treat each other with respect.

⭑ Optimism over Pessimism. Avoid cynicism.

We approach our work and our coworkers with positivity. We like the improv rule of “Yes and” instead of our initial instinct being “No” since starting with “No” tends to stifle creativity. We want to aim to assist the person.

Why is this important? Pessimism and cynicism are contagious and drain energy and creativity. A single pessimistic or cynical person can destroy the productivity of an entire team (study).

Limiting principle? We still must be realistic and provide valid feedback. There’s always a way to provide honest feedback while still remaining positive. We also don’t want to create cases where one engineer is blocking another engineer and the onus is solely on the blocker to unblock the work. It’s a shared responsibility to try to get to “Yes”.

⭑ Clean escalations when there are disagreements

When we disagree, each side should strive to understand the other side. When both sides can articulate the other’s point of view, they are able to distill the disagreement down to its essence. A clean escalation is one where both parties bring the disagreement to a third party in order to help mediate or arbitrate the decision. A dirty escalation is where one party escalates to the third party without the other. There should be a willingness to disagree and commit when a consensus can’t be reached.

Why is this important? Many disagreements are not actually disagreements but rather the two sides talking past each other or failing to understand the other’s point of view. When the parties truly understand each other’s point of view, there often doesn’t need to be an escalation. If an escalation is required, it’s more efficient when the disagreement has been distilled down to its essence.

Empowering Engineers

We hire talented people and empower them to accomplish our purpose. Engineering should be rewarding and building should be a creative process. Easy things should be easy and hard things should be in service of the actual business problems versus fighting with the infrastructure or tools.

⭑ Context over control

We believe in providing engineers and engineering teams with the context they need to make sound decisions as opposed to being order takers. We want engineers to operate with autonomy as part of their cross-functional teams while taking into account the needs of their stakeholders. It’s the obligation of leadership to provide the context such as our strategy, our priorities, and our resources so engineers can make sound decisions.

Why is this important? Engineers are problem-solvers that collaborate with their cross-functional partners to build great products for our customers and great infrastructure for other engineers and stakeholders. We want to avoid a permission-seeking culture where engineers feel they need to be told what to do or seek management approval. An engineer at Nextdoor should not function as an API that is called by their Engineering Manager or Product Manager to mindlessly translate tasks and specs into Pull Requests.

⭑ Infra > Tools > Docs > Process

We prefer solving problems at the infrastructure level to reduce the burden on our engineers and to implement consistency across the company. If we can’t solve it at the infra level, we’d prefer solving it with tooling rather than through documentation or process.

Why is this important? We want our engineers to be able to be as productive as possible. Process can slow engineers down, even when there is the best of intentions. Documentation gets out of date or is undiscoverable. Infra automates the work away and reduces cognitive overhead. Great tooling can often replace manual processes.

⭑ Self-service over file a ticket

We prefer self-service tools over processes that require human intervention.

Why is this important? Self-service can be instantaneous. It avoids blocking an engineer on another person and reduces context switching. We strive to reduce dependencies and processes that require human intervention. An example is the impersonation permission flow which allows an engineer to obtain temporary permission to impersonate a neighbor without requiring human intervention in a safe and auditable manner.

⭑ Transparent Decisions

We are transparent with our decisions, explaining the reasons behind our decisions, and the decision-making process itself. We do our best to document and share our decisions, and make meeting notes visible to the entire company when possible. At Nextdoor we use the SPADE framework to document and broadly share important decisions for product, engineering and business topics.

Moving Fast

We believe that moving fast is essential for us to accomplish our purpose. This is encapsulated in our company core value of “Experiment and learn quickly”. We also recognize that there are tradeoffs between moving fast now versus moving fast over the long term.

⭑ Under-engineering is preferable to over-engineering

We prefer to validate our product and engineering decisions quickly and add things later that we missed. Therefore, we want to architect our systems taking into account known requirements and build what is truly needed.

Why is this important?

A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over with a working simple system. — Gall’s Law

Limiting principle? We should be careful to not box ourselves into a corner with our early decisions but also not to waste resources over-engineering something where we don’t understand the long term requirements.

⭑ Working code over comprehensive documentation

We prefer to bias towards building and prototyping over writing long architectural docs and blocking on architectural approvals. We agree with the Agile Manifesto.

Why is this important? We want to be as agile as possible and learn through experimentation and iteration. A prototype, like a picture, says a thousand words.

Limiting principle? Large changes that impact many engineers often require more up-front design and stakeholder feedback. See Farm for Dissent. We should write overview docs and how-to-docs for infrastructure that is used by many engineers. We are not against documentation. This is a “bias towards” not an “all or nothing” approach.

⭑ Build iteratively

We prefer to build iteratively such that our changes deliver value incrementally.

Why is this important? We want to avoid multi-quarter projects where no value is delivered until the very end of the project. Industry experience shows that these projects tend to be high risk and often fail. Almost all projects can be broken up into milestones that deliver value iteratively along the way and help validate the direction, build momentum for the team, and avoid trying to hit a moving target where the requirements change over time.

Limiting principle? Larger, strategic projects may take longer to deliver value. To ensure that we are on the right track and making continuous progress, these projects should have milestones that incrementally validate themselves if the value can’t be delivered more iteratively.

⭑ Infrastructure Should Be Easy/Secure/Fast By Default

Our infrastructure should enable engineers to fall into the “pit of success”. We pick defaults that should lead to the right outcomes. We strive to eliminate foot guns. We strive to minimize writing the same boilerplate code over and over. We optimize the infrastructure to make the lives of the customers better as this is the direction of the leverage. The scope and responsibility of the infrastructure maintainers expand to accomplish this goal. Building on top of our infrastructure should feel like playing with legos. You can’t hurt yourself playing with legos, but you can build something great.

Why is this important? Our engineers are more productive when the infrastructure allows them to focus on the product value rather than solving recurring problems that can be solved once for everybody.

⭑ Minimize repositories and services

We strive to minimize the number of repositories and services that need to be touched to build an end-to-end product change. We explicitly want to identify having micro-services that provide middle-tier functionality as being an anti-pattern.

Why is this important? We measure our velocity by how quickly we can deliver end-to-end improvements to our customers. Even though having more services can make it faster to merge a single PR, it slows down product development when an end-to-end feature requires merging into multiple repositories, sequencing the deployments, and maintaining protocol compatibility between services. In addition, it’s impossible to factor product functionality correctly from the beginning as products evolve and the requirements change. Refactoring code within a single service is much easier than refactoring the services themselves.

Limiting principle? Good candidates for services are ones where the interface is extremely stable and product changes rarely need to be coordinated across protocol boundaries (e.g. DynamoDB, Redis, Postgres). Separate vertical products that have very little coupling to other products may also be good candidates (e.g. Ads).

⭑ Two-way doors are better than one-way doors

We prefer decisions that are easy to undo. We optimize for making cheap mistakes, since making mistakes is unavoidable. When considering a one-way door, we should heavily lean on Farm for dissent.

Why is this important? Making mistakes that are easy to undo means we can move faster and learn quickly. One-way doors require a lot of time and energy since the stakes are much higher.

⭑ Testability and Testing

Our code should be easy to test and well-tested. When building libraries and infrastructure, it’s not enough to write unit tests for the library. The library should be written such that the code that uses it is also easy to test. A library that makes it hard to test the code that uses it is not a very good library.

Why is this important? Unit, integration, and automation tests help us move faster. While it might slow down the initial development to write the tests, in the long run the tests allow us to move faster in the future and avoid costly regressions.

Limiting principle? We are not a test-driven development shop that requires 100% code coverage. Writing and maintaining tests have a cost and a benefit. We should make writing tests as easy as possible. We should have a bias towards writing tests, but we should be pragmatic and weigh tradeoffs.

⭑ Observability

We should strive to make our services and applications have a high degree of observability. Analytics, logging, error handling and metrics are a critical part of everything we build.

Why is this important? Nextdoor is fundamentally a complicated system. It’s made especially complicated because it’s an ecosystem that has network effects where users affect each other’s behavior. It’s critical that we write our products and services to be as observable as possible so that we know they’re working as expected and so we can quickly perform root cause analysis when something goes wrong. A small amount of work to build observability upfront generally saves countless hours later.

Collective Code Ownership

Collective code ownership stems from our belief that Software Engineering is a Team Sport and supports our desire to Empower Engineers and to Move Fast. Engineers need to be able to easily read, understand, and modify code written by other engineers.

⭑ Stewardship over strict code ownership

Our intention is similar to what Martin Fowler describes as weak code ownership. Engineers should not act defensively when another engineer or team desires to make a change to the code they generally maintain. Instead, they should act as stewards of the code advising other teams on how best to work together to facilitate a change that furthers our purpose. This should be in the context of the ProdDev ownership process where the team owning the area of the product affected should be the approver of the change.

Why is this important? We don’t want our engineers acting territorially. This slows down innovation and makes cross-cutting changes more difficult. We generally want to rely on engineers to exercise good judgment when seeking code reviews rather than requiring strict approvals from code owners. This is enabled by having a safe infrastructure.

Limiting Principle? We expect engineers to exercise good judgment and seek feedback and code reviews from the persons or teams that are best able to review the change. We expect engineers to follow the ProdDev ownership process.

⭑ Minimize languages and frameworks

We strive to minimize the number of languages and frameworks used at the company.

Why is this important? We want engineers to be able to contribute across the product and at different levels of the stack. This enables engineers to work in more areas of the product, reduces dependencies between teams, and increases agility of the organization. This also reduces silos and allows us to work as one engineering team.

Limiting Principle? Often there are good reasons to introduce a new language or framework. This must be balanced against the long term maintenance cost and complexity introduced to the engineering organization. It should be done with strong intention rather than convenience. Valid reasoning: “We should write the Ad code in Java because Java is the standard language across the broader advertising ecosystem and all the libraries assume Java.” Less valid: “There’s a cool new library in Rust. Let’s write this service in Rust.”

⭑ Opinionated conventions

We should have conventions that are opinionated and consistent across all of engineering. Our aspiration is that code written by multiple engineers should be indistinguishable in style, patterns, and structure.

Why is this important? We want engineers to easily move between areas of the code base in order to build end-to-end functionality for our customers. Code is easier to read and modify when we have consistent conventions. We can build better infrastructure and tooling around known conventions and best practices.

Optimize for Learning

We foster a culture of learning that optimizes for exploration, openness, and creativity. We hire employees who are united by our shared curiosity and desire to apply our learnings towards accomplishing our purpose.

⭑ Give and receive feedback with good intent

We should give and receive feedback with the assumption of good intent. When giving feedback, we should strive to make it constructive, timely, and actionable. When receiving feedback, we should assume the giver is trying to help us improve. We should always acknowledge and be thankful for the feedback. That does not mean the feedback must be accepted. It’s also okay to thoughtfully consider and reject feedback. When a person acts on our feedback, we should close the loop by acknowledging the improvement.

Why is this important? We’re a growth-oriented culture and we learn and improve through feedback. We want engineers to feel comfortable providing feedback because withholding it denies the other person information they may need to grow and results in worse outcomes for the company.

Limiting principle? Feedback is never an excuse to create a culture of “brilliant jerks”. Feedback should never be weaponized. Feedback should only be given when the intent is to help the person improve and the feedback is actionable.

⭑ Farm for dissent

Engineers should socialize their ideas to seek out diverse perspectives from both inside and outside engineering. The larger the risk and cost of a mistake, the more important it is to seek out feedback. Engineers should exercise good judgment on who are the best people to provide feedback based on the particular domain of the change. Often the best people to consult are in other functions such as Data Science, Marketing, Product, Design, ProdOps, Legal,, etc.,

Why is this important? Everybody has blind spots and we reach better architecture and design decisions when we seek out feedback and diverse perspectives.

⭑ Whisper Wins. Sunlight Failure.

We should strive to shine as much light on our failures as possible so that the organization can learn from the mistakes. Failure is an inevitable part of the process. We celebrate our wins but we should be humble and avoid building a culture of bragging.

Why is this important? We want to create a culture that thinks big and takes risks. Many things we try will fail and we want to learn from failure. We should never stigmatize failing.

⭑ Retrospective Culture and SEVs

Processes like retrospectives and SEVs (Site EVents) are for learning, never for blaming. We learn from our outages and our mistakes and make improvements to our infrastructure and tooling to try to prevent similar issues in the future.

Why is this important?

If you’re not making mistakes, then you’re not doing anything. I’m positive that a doer makes mistakes. 

-John Wooden

Craftsmanship

Craftsmanship is generally defined as skill in building something that is of high quality where great attention was paid to the details and no corners were cut. This is an aspirational goal and it’s often in tension with many of our other principles (e.g. Moving Fast).

At Nextdoor, we do not adopt a pure craftsmanship approach as that would almost certainly mean we were prioritizing perfection over-delivering value, and moving fast. Instead, we should always understand what a well-crafted solution looks like. When we compromise, it should never be because we were lazy or sloppy. Rather, it should always be due to a tradeoff that was made in service of our purpose. We should take great pride in what we build. A compromise that is made for the right reason can still be a point of pride.


Let us know in the comments what are the principles that resonated with you and if you have examples or other engineering principles that you apply within your teams. And also check out our Careers page, we have many open opportunities across all our teams and functions.

Theme is edited