Structure engineering organizations for speed, autonomy, and alignment. Covers team topologies, Conway's Law, inverse Conway maneuver, stream-aligned teams, enabling teams, and the patterns that scale engineering organizations from 10 to 1,000 engineers.
Engineering org design is the deliberate shaping of teams, roles, workflows, and decision-making structures to align engineering capacity with technical and business outcomes. It matters when teams grow beyond a handful of people, when technical debt accumulates, and when engineering struggles to keep pace with product velocity. This page guides leaders through the critical actions of designing and evolving engineering organizations—what to do, how to do it, and what to watch for.
When a team of 5–7 engineers begins to feel constrained by shared responsibilities, unclear priorities, and slow delivery, it is time to formalize the org design. The first step is to define team boundaries using the bounded context principle: each team owns a distinct part of the system with well-defined inputs, outputs, and responsibilities.
Teams should be sized between 6 and 12 members. Smaller teams are more agile; larger ones risk becoming silos. A team of 8 should be able to deliver end-to-end features without blocking on other teams. The team structure includes:
To define a team’s scope, create a team charter using a standard format:
## Mission
Deliver end-to-end payment processing, including transaction lifecycle, reconciliation, and reporting.
## Scope
- Accepting payments via card, bank transfer, and digital wallets.
- Handling refunds, chargebacks, and disputes.
- Integrating with external providers (Stripe, Adyen, PayPal).
- Managing billing cycles and subscriptions.
## Responsibilities
- Own the `payments-service` and `billing-ui`.
- Set up and maintain CI/CD pipelines for the payment ecosystem.
- Define and enforce API contracts with other teams.
## Dependencies
- Requires data from the `user-service` and `reporting-service`.
- Dependent on `auth-service` for user identity.
- Publishes events to `event-bus` for downstream processing.
## Success Metrics
- 99.9% uptime of payment processing.
- Average latency < 200ms for payment creation.
- 95% of invoices generated within 1 hour of due date.
Use git to version team charters in the org/teams/ directory. Each team maintains its charter in org/teams/payments.md, with a team.yaml file for machine-readable metadata:
team:
name: "Payments"
slug: "payments"
size: 8
lead:
github: "jane-doe"
role: "engineering-lead"
product-owner:
github: "alex-smith"
role: "product-owner"
tech-stack:
- "Go"
- "PostgreSQL"
- "gRPC"
- "Kubernetes"
dependencies:
- "user-service"
- "event-bus"
- "auth-service"
key-metrics:
- "uptime: > 99.9%"
- "latency: < 200ms"
- "invoice-generation: < 1h"
A team’s charter is not static. It should be reviewed quarterly. When a team grows beyond 12 members, or when dependencies become a bottleneck, it is time to split.
When a team becomes too large or too dependent, splitting is necessary. The decision to split must be driven by ownership signals: teams that frequently need to coordinate, share data, or align on APIs.
The process for splitting a team is:
For example, splitting the Payments team into Payments Core and Payments Extensions:
The transition plan includes:
payments-core-api.yaml file that defines the interface:api:
name: "Payments Core"
version: "v1"
base-url: "https://api.payments-core.example.com"
endpoints:
- path: "/v1/transactions"
method: POST
request:
type: "json"
schema:
required:
- "payment_method"
- "amount"
- "currency"
properties:
payment_method:
type: "string"
enum: ["card", "bank_transfer", "digital_wallet"]
amount:
type: "number"
format: "decimal"
currency:
type: "string"
pattern: "^[A-Z]{3}$"
metadata:
type: "object"
additionalProperties: true
response:
type: "object"
properties:
transaction_id:
type: "string"
format: "uuid"
status:
type: "string"
enum: ["pending", "completed", "failed", "reversed"]
created_at:
type: "string"
format: "date-time"
payments-extensions service, while Payments Core owns payments-core, and all new features in payments-extensions are reviewed by Payments Core.Failure mode: teams split but continue to share the same CI/CD pipeline, resulting in dependency drift—a change in one team’s service breaks the other’s, but the change is not coordinated. The solution is to require pull requests with team-reviewers in team.yaml, and to run ci-checks using git hooks and make:
.PHONY: ci-checks
ci-checks:
@echo "Running CI checks..."
@npm run lint
@npm run test
@docker build -t app:latest .
@echo "✅ All checks passed"
As teams grow, roles must evolve. The core roles are:
Each role has a responsibility matrix:
| Role | Ownership of | Collaboration With | Decision Authority | Key Deliverables |
|---|---|---|---|---|
| Engineer | Feature delivery | Team, Product Owner | Medium | Code, PRs, documentation |
| Engineering Lead | Team health, technical roadmap | Cross-team, Product, Platform | High | Team charter, architecture decisions, hiring |
| Principal Engineer | Technology strategy, standards | All teams, CTO, Platform | Strategic | Architecture reviews, decision records, training |
| Staff Engineer | Domain ownership, initiative delivery | Cross-team, Engineering Lead | High | Domain architecture, RFCs, training |
The engineering career ladder is not a document—it is a process. When an engineer applies for promotion, they submit a promotion package:
Promotion decisions are made in engineering review meetings, held biweekly. Each meeting uses a standard agenda:
meeting-agenda.md file: # Engineering Promotion Review: Q3 2024
## Attendees
- Jane Doe (Engineering Lead, Payments)
- Alex Smith (Principal Engineer)
- Sam Lee (Staff Engineer, Infrastructure)
## Agenda
1. Review: Lena Chen (Engineer → Senior Engineer)
2. Review: Marcus Patel (Senior Engineer → Staff Engineer)
3. Discussion: Standardizing error logging across services
4. Action items from previous meeting
## Decision Format
- Each candidate: 10 minutes presentation, 15 minutes discussion.
- Voting: yes/no/strong yes/no/strong.
- Final decision: majority vote.
decision-record.md templates:# Decision Record: Standardizing Error Logging
## Date
2024-07-15
## Context
- Multiple services use different logging formats.
- Errors are hard to correlate across services.
- SREs spend 30% of time debugging with inconsistent logs.
## Options
1. Adopt JSON logging with structured fields.
2. Use OpenTelemetry logs.
3. Standardize on a single log format (e.g., `logfmt`).
## Decision
- Adopt JSON logging with structured fields.
- All new services must use `json-logging` module.
- Existing services to migrate within 6 months.
## Rationale
- JSON is widely supported, human-readable, and machine-parsable.
- Enables better observability and alerting.
## Implementation
- Create `common-logging` library in Go and TypeScript.
- Enforce via CI: `make lint-logs` checks for required fields.
## Owner
- Jane Doe (Engineering Lead, Observability)
When teams grow, coordination becomes the primary friction. The solution is a cross-team coordination rhythm:
Syncs follow a standard format:
syncs/2024-07.md: # Biweekly Sync: July 15–29, 2024
## Attendees
- Payments Team
- Auth Team
- Infrastructure Team
- Observability Team
## Agenda
1. Payments Team: Q3 roadmap (10 min)
2. Auth Team: OAuth 2.0 migration (15 min)
3. Infrastructure Team: Kubernetes upgrade timeline (10 min)
4. Open discussion: shared service contracts (20 min)
## Action Items
- [ ] Jane to send updated API spec by July 22.
- [ ] Alex to schedule a joint demo with Auth and Payments by August 1.
action-items.md file:## Action Items from July 15 Sync
- [x] Jane to send updated API spec by July 22. (Due: 2024-07-22)
- [ ] Alex to schedule a joint demo with Auth and Payments by August 1. (Due: 2024-08-01)
- [ ] Sam to create a dashboard for shared service uptime. (Due: 2024-08-15)
Failure mode: syncs become status updates without outcomes. To avoid this, each sync must end with decisions, action items, and next sync agenda—all captured in a syncs/2024-07.md file and committed to git.
Org design is not a one-time event. It must evolve. The key feedback loop is org health reviews, held every 6 months.
Each review includes:
kubectl get pods -A to check service availability.psql -c "SELECT service, avg(latency), count(*) FROM errors GROUP BY service;" to identify high-latency services.ci-checks logs to detect flaky pipelines.The outcome is a org design review report, stored in reports/org-review-2024-06.md:
# Engineering Org Design Review: June 2024
## Summary
- Teams are aligned on mission.
- Cross-team collaboration is improving.
- High latency in `billing-service` and `auth-service`.
## Key Findings
- 70% of engineers feel their team’s charter is outdated.
- Payments and Auth teams have overlapping responsibilities.
- CI/CD pipelines are inconsistent across teams.
## Recommendations
- Update team charters biannually.
- Create a shared service registry (using `team.yaml` and `api.yaml`).
- Standardize CI/CD with `make ci-checks` and `git` hooks.
## Action Items
- [ ] All teams to update charters by July 30. (Owner: Jane Doe)
- [ ] Build shared service registry in `org/services/`. (Owner: Sam Lee)
The org design process is now self-sustaining: teams create, review, and evolve their structures using shared tools, patterns, and standards. The organization is not just a collection of teams—it is a living system.
This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy