Architecture

Design Instagram

Designing Instagram is one of the most frequent question asked in the interviews. Lets discuss the design approach and various choices.

Requirements:

  1. User can post an image
  2. One user can follow the other user 
  3. Generate the home feed for the user

Design Tenets

  1. GraphQL solves the problem of underfetching and overfetching of the data. It also reduces the number of API calls by returning the required data in signal backend calls. The GraphQL graph schema is also suitable for exposing the API for the social network, so we would be using GraphQL for the API.
  2. The images would be stored in the object store similar to S3.
  3. Authentication and authorization edge functions would be implemented as middleware with the graphQL service
  4. We would use graphQL subscribe type to send the real time updates to the client
  5. The CQRS pattern would be used for microservice architecture. The read service would read the data from the graph database’s replicas. Read service would implement feed API while the command service would implement follow and upload API. 

Architecture

GraphQL API

// Instragram Post

Type Post {
Id: ID !
Name: String !
Url: String!
Description: String
}

// User information
Type User {
Name: String !
Followers: [User !]// List of posts created by this user
Posts: [Post]// Feed for the user
Feed: String
}

Type Mutation {
doPost(
Name: String !,
Url: string !,
Description: string
)
}

Type Query {
allUsers(user:id): User!
}

Type Subscription {
newPost: Post!
}

Schema = {
Query: Query,
Mutation: Mutation,
Subscription: Subscription
}

Datastore

We would be using the Neo4j database for storing the posts. The database schema would be as following:

Nodes :

:User {
UserName: String
}

:Post {
Name: String
Url : String
Description: String
}

Relationships:

[has_posts], [follows]

Neo4J would be deployed as a cluster with the core servers and the read replicas. 

Neo4J deployment

Observability

We need to collect metrics, log and use distributed tracing for the application. For collecting metrics, prometheus can be used. For logs, fluentd can be used which can use elastic search as the log sink . Fluentd is a recommended solution for log aggregation on docker.  For distributed tracing, the common solutions are Jaeger or Zipkins. The distributed tracers, propagates a distributed context and which correlates all the logs for a request. 

Circuit breakers and bulkhead are the command patterns for handling the service failures. Rate limiters would be middleware on the servers.

References:

  1. Graphqlbin playground http://snowtooth.moonhighway.com/
  2. https://neo4j.com/docs/operations-manual/current/clustering/introduction/

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button