Pair Programming Interview Prep
1. Define Functional Requirements:
What the users should be able to do. Clarify by asking: "what core features need to be implemented?"
- Establish Core Entities
- Is Extract, Transform, Load (ETL) necessary?
Define the contract between the system and its users
- REST (Representational State Transfer): Uses HTTP verbs (GET, POST, PUT, DELETE) to perform CRUD operations on resources.
- GraphQL: Allows clients to specify exactly what data they want to receive, avoiding over-fetching and under-fetching.
- RPC (Remote Procedure Call): Faster than REST for service-to-service communication. Use for internal APIs when performance is critical.
Example:
POST /v1/tweets
body: {
"text": string
}
GET /v1/tweets/{tweetId} -> Tweet
POST /v1/users/{userId}/follows
GET /v1/feed -> Tweet[]
Derive the current user from the auth token, not from user input.
2. Define Non-functional Requirements
What the system should be able to do. Clarify by asking "what part of the system?"
- Capacity is often unncessary to calculate. Skip upfront and calculate when it becomes relevant.
- CAP Theorem: Prioritize consistency or availability?
- Environment Constraints: Resource limitations
- Scalability: What parts of the system needs to scale? Does it to prioritize reads or writes?
- Latency
- Durability: How is data loss handled?
- Security: How secure does the system need to be? Consider data protection, access control, and compliance with regulations.
- Fault Tolerance: How does the system handle failure?
- Compliance: How will compliance be enforced?
Design the System
- How does the data flow? Begin from the request and end with the response. How does the state of the data change within the service function chain?
::: info
Focus on the functional requirements (the core features that need to be implemented). Focusing on nonfunctional requirements can lead to scope creep and complexity; which in turn the solution will never be completed (or delivered).
:::
-
Fanout-on-write: when a user makes a post, it is written into 1,000 timelines
- Use this when reads are more frequent than writes.
- pay the cost when posting; fast reads, expensive writes.
-
Fanout-on-read is the pull method: when a user opens their feed, it pulls 1,000 post from the people they follow.
- Use when writes are frequent
- pay the cost when reading; cheap writes, expensive reads.
-
Most systems do a hybrid approach: fanout-on-write for less popular accounts, fanout-on-read for popular accounts.
Networking
- HTTP over TCP
- WebSockets: useful for real-time updates. Bidirectional communication (e.g. chat or streaming). Needed when data is pushed to the server regularly.
- Server-Sent Events (SSE):useful for real-time updates. Server to client push. Simpler to implement.
- WS and SSE are stateful
- WS requires L4 Load Balancer to persist the connection
- gRPC: service-to-service communication; high performance. Faster than JSON over HTTP.
API
- REST examples:
GET users/{id}orPOST /events/{id}/bookings. - GraphQL: over-fetching and under-fetching.
- query parsing + schema validation
- Pagination for large results
- JWT tokens for authentication
Data Modeling
Relational databases
- e.g. Postgres
- when data is structured with clear relationships
- Normalization: data split across multiple tables to avoid duplication
- denormalization: duplicate data and make reads faster. For read-heavy systems where data rarely changes (updates can be expensive).
NoSQL
- e.g. DynamoDB
- partition key and sort key based on access patterns
- Most read value for partition key.
- Have to know queries upfront.
Key Technologies
- API Gateway route requests to the backend. Also logging, auth, and rate limiting.