Showing posts with label bff. Show all posts
Showing posts with label bff. Show all posts

Sunday, April 27, 2025

Design uplift seris- Part 4 BFF design ( in progress)

 

Part 1 BFF design article explains  what are the main advantages of Graphql for implementing BFF and important scenarios where Graphql can be used. Other aspects like security and common anti design patterns and  how to over come them. Articles don't discuss  about in-depth explanation of how to design schema ,query , types and mutations  .

  Right now selecting a particular graphql server mostly depend on the programming language used  for application development., there are few vendors having solution and can be adopted without much comparison              of   alternative deigns. The choice  mostly   linked to the programming language being used             in     application/ product. But this will change as BFF is very much part of best design patterns    now             like api layer design or repository pattern , slowly BFF layer become part of most of new design / architecture diagrams . which indicates that better tooling and handling complex scenarios needs better choice interms of tooling along with choice of Graphql server. So the article will explain total end to end system design not just setting up Graphql server. Newly developed solution for graphql server like Yogagraphql already has more than 40k downloads. It shows that there will be more design alternatives going forward.

          If we look at some of the security  risks  discussed  in Book                "Black Hat GraphQL"  it also give                examples how                   graphql servers by few vendors providing additional security.             So there are many parameters along with setting up graphql             server. Security, schema generation, managing sub graph     -            and moving towards federation graphql .  All these parameters         helps to     design better grapql eco system. I am using apollo             client  which can cache client side data if the query is not                 changed. These     are few      features by these vendors some             times can  influence  whole     design.


 Part 2 in this article we can look at the available design options and the suitable use case will be discussed. It is important to understand in depth capabilities of the existing frameworks which can help to quickly bring Graphql server and Graphql client and can also add lot of features like security , build , logging  , scalability and other components as plug and play ,  as these  frameworks  are designed with lot of add on components and easy to integrate using API  .

Design Objectives

Let us consider few important use cases where Graphql being used extensively. One of the design discussion is about all the objects in graphql are connected like graph and also query represents closely with the data design.

 


There are many articles  discussing above  inherent feature of Graphql and advantages and disadvantages. As one article explains it as schema is graph and queries results in tree only. The articles also extending advantage of using graphql for graph based data bases. It also explains with good examples and how to validate and maintain data quality so that it works with graphql better way.

One way to look at designing Graphql server with Neo4j or similar frameworks are  more close to data driven design . There could be many variations to above.

There few advanced graphql servers they can help to expose DTO objects as graphql end points.  Hasura is one such grapqhql implementation. Similar thinking and design but Hasura will talk more about DTO object instead of data base type.

Let us look at AWS  design for Graphql server  with the  APP Sync based design.


 

As explained by AWS  the three subgraphs are composed into the Fusion gateway which is ran as a Fargate service behind an Application Load Balancer.

Above system developed by aws brings in the following advantages as it was shipping graphql server with lot of features already available and which can be extended based on application design. Here are few advantages of using above

Real-time data synchronization using subscriptions. Integration with AWS services like DynamoDB, Lambda, and S3.Simplified authorization with Amazon Cognito, API keys, and IAM.

Api  load balancing  and  security capability of IAM and also can make use of AWS components quickly.  Dev focus could be   implementing  schema , types and query files. This kind of design approach where lot of components can be plugged in can reduce development time . we can discuss more about  some of the major features which can be more attractive in selecting the design  when we try to compare different designs available for a real time example. 

Hot Chocolate: Hot Chocolate is a GraphQL platform for that can help you build a GraphQL layer over your existing and new infrastructure.

More precisely Hot Chocolate is an open-source GraphQL server for the Microsoft .NET platform that is compliant with the newest GraphQL October 2021 spec + Drafts, which makes Hot Chocolate compatible to all GraphQL compliant clients like Strawberry ShakeRelayApollo Client, and various other GraphQL clients and tools.  As it is more Microsoft platform based design and can work closely with Microsoft infrastructure.

Express Graph ql, Appollo Graphql server and server other   popular frameworks available to implement grpahql server. We can dive deep when we try to design couple of  real time example after discussing some more important design patterns and frameworks.

Design Patterns and Use cases

Let us consider scenario where an monolithic application having MVC pattern which was adopted by many legacy systems. When it is required to redesign above systems based on latest micro service based cloud enabled applications , new patterns like BFF, serverless and other  technologies are recommended for new application design. 

Use case 1: Refracting legacy Application:

In a simple design if all controller end points are mapped to an graphql end point and Client which is view  decoupled form MVC pattern it is one way to break monolithic application. This one is most adopted  approach in industry  I can see this approach is  best use case in industry for introducing BFF layer and graphql.

                   Let us  look at complete set of components and process                        involved in adopting Graphql

Design Graphql Server which also involve designing schema, query, types     and  resolvers to fetch data.

Designing some cache components  and optimizing data fetching using          pagination  and error handling, Client side design to interact with grapqhql  server.

Next will be API management related aspects like versioning and load    balancing.

Tooling : Here comes the major design decision as lot of vendors gives readily available schema generators, Visual designers for schemas ,query and  types  design,  testing frameworks  and every thing required to set up Graphql server  and to perform above 4 step with attractive  low code no code kind of  approach. So all  pending work could be   just hooking resolvers with data end points.    

The above refactoring and redesign exercise  can be extended to address lot of design considerations like separation of concerns  or abstracting   data 

We can discuss in depth scenarios for above design transition form MVC to Graphql server and then we can consider different platforms available which can be best fit for the above refracturing or tech refresh exercise.

Use case 2 API Aggregation : Aggregating multiple apis internal and./or external and abstracting api details from Clients.

Use case 3 BFF Design: Building more modular patterns in application design using BFF.

User case 4 Using Graphql along with Micro srvices : Graph QL for managing microservices and service mesh.

Here is one example of robust architecture for use case 4 using applo federation and microservices with an Api gateway 

Ref: https://talashlogs.blob.core.windows.net/talash-drive/leveraging-graphql-for-next-generation-api-platforms.pdf

Important design aspects for this reference architecture are : 

Appollo provides lot of ready to use components along with Graphql server. As discussed above it is like a platform which can give lot of other components to maintain Graphql infrastructure and quickly build application. As shown in this diagram Apollo provides a GraphQL developer platform (GraphOS), which includes developer tooling, a schema registry, and a supergraph CI/CD pipeline and high-performance supergraph runtime.

Even Appollo clients provided can manage cache control at client side . Cache  management is bit tricky and needs  more components to maintain server cache and client cache which we can discuss later.

Other components in diagram are Kong API gateway . This could be any other API manager  . Important point here is Micro services needs service mesh to communicate and then they are connected to Graphql server. Bit of load balancing and security achieved with these API gateways embedded in the design. 

Security is often handled with a defense-in-depth or zero-trust approach, where each layer of the stack provides security controls for authentication, authorization, and blocking

malicious requests. Client-side traffic shaping with rate limits, timeouts, and compression can be implemented in the API gateway or supergraph layer, and subgraph traffic shaping

(including deduplication) can be implemented at the supergraph layer. Observability via Open Telemetry is supported across the stack to provide complete end-to-end visibility into each

request via distributed tracing along with metrics and logs. 

 

(Apollo Router).


Here is another way to classify above use cases.- 

 

Pattern

Advantages

Challenges

Best Use Cases

Client-Based GraphQL

Easy to implement, cost-effective

Performance bottlenecks, limited scalability

Prototyping, small-scale applications

GraphQL with BFF

Optimized for clients, better performance

Increased effort, higher complexity

 Applications with diverse client needs

Monolithic GraphQL

Centralized management, consistent API

Single point of failure, scaling issues

Medium-sized applications, unified schema

GraphQL Federation

Scalable, modular, team autonomy

Increased complexity, higher learning curve

Large-scale, distributed systems


Best practices

What are the key principles of schema design in GraphQL?

Designing a GraphQL schema with flexibility and scalability in mind involves several key principles that ensure the schema can grow and adapt to changing requirements while maintaining performance and usability.
  • Unified Schema: A GraphQL schema defines a collection of types and their relationships in a unified manner. This allows client developers to request specific subsets of data with optimized queries, enhancing flexibility.
  • Implementation-Agnostic: The schema is not responsible for defining data sources or storage methods, making it adaptable to various backend implementations without requiring changes to the schema itself.
  • Field Nullability: By default, fields can return null, but non-nullable fields can be specified using an exclamation mark (!). This provides control over data integrity and error handling, contributing to robust and scalable schema design.
  • Query-Driven Design: The schema should be designed based on client needs rather than backend data structures. This approach ensures that the schema evolves with client requirements, supporting flexibility and scalability.
  • Version Control and Change Management: Maintaining the schema in version control allows tracking of changes over time. Most additive changes are backward compatible, but careful management of breaking changes is essential for scalability.
  • Use of Descriptions: Incorporating Markdown-enabled documentation strings (descriptions) in the schema helps developers understand and use the schema effectively, promoting a flexible development environment.
  • Naming Conventions: Consistent naming conventions, such as camelCase for fields and PascalCase for types, ensure clarity and ease of use across different client implementations, aiding in scalability

Tools and devops 


References:

Apollo graphql federation:

 https://talashlogs.blob.core.windows.net/talash-drive/Apollo-graphql-at-enterprise-scale-final.pdf

Security and pen test

https://talashlogs.blob.core.windows.net/talash-drive/Black+Hat+GraphQL_bibis.ir.pdf

PentestingEverything/API Pentesting/GraphQL at main · m14r41/PentestingEverything

Design patterns

https://drive.google.com/viewerng/viewer?url=https://talashlogs.blob.core.windows.net/talash-drive/API+Composition+Pattern+with+GraphQL.pdf

Naming and best practices and schema design

GraphQL: Standards and Best Practices | by Andrii Andriiets | Medium

GraphQL Best Practices for Efficient APIs

Monday, July 31, 2023

Backends for Frontends Pattern AWS

 Ref:https://aws.amazon.com/blogs/mobile/backends-for-frontends-pattern/


Interesting points and differnt approch to design BFF:


AWS AppSync is a fully managed service that makes it easy to develop GraphQL  In this article it explains how to  bring API  functionality thorough BFF to client . Architecture is completely based on events driven which makes more interesting from integration point of view. 


In this blog post, we describe how you can improve end-user customer experience on your User Interfaces (UI) by implementing the Backend for Frontend pattern and providing real-time visual updates when your microservices raise events about mutations in their domain aggregates.

The solution proposed combines two patterns: 1) the Backends for Frontends (BFF) pattern, where applications have one backend per user experience, instead of having only one general-purpose API backend; and 2) the Publisher–Subscriber (pub/sub) pattern, where microservices announce events to multiple interested consumers asynchronously, without coupling the senders to the receivers. When combined, these two patterns allow frontend clients to load UI-ready data projections and to refresh the UI with event-driven notifications, resulting in a high-performant near-real-time experience for end-users.

To explain the solution to both REST and GraphQL API developers, we provide two similar architecture diagrams addressing each API technology.

The BFF pattern

According to Sam Newman, the Backend For Frontend (BFF) pattern refers to having one backend per user experience, instead of having only one general-purpose API backend.

Traditionally, the approach to accommodating more than one type of UI is to provide a single, server-side API, and add more functionality as required over time to support new types of mobile interaction. The following challenges may result from this approach:

  1. Mobile devices make fewer calls, and want to display different (and probably less) data than their desktop counterparts – this means that API backends need additional functionality to support mobile interfaces.
  2. Modern application UIs are increasingly adopting reactive strategies to provide real-time feedback to end-users (for example via WebSockets), and different devices may implement different technology stacks to support it.
  3. API backends are, by definition, providing functionality to multiple, user-facing applications – this means that the single API backend can become a bottleneck when rolling out new delivery, due to the many changes being made to the same deployable artifact.

To address these challenges, Sam suggests that you should think of the user-facing application as being two components: a client-side application living outside your perimeter, and a server-side component (the BFF) inside your perimeter. According to him, the BFF is tightly coupled to a specific user experience, and will typically be maintained by the same team as the user interface, thereby making it easier to define and adapt the API as the UI requires, while also simplifying the process of lining up releases of both the client and server components.

Following Sam’s suggestion, the BFF pattern has been adopted by companies like Netflix, where their Android team seamlessly swapped the API backend of the Netflix Android app, enabling them to work with their endpoint with increased level of scrutiny, observability, and integration with Netflix’s microservice ecosystem.

Components of an event-driven BFF on AWS

Assuming that you already have an event-driven architecture in place, regardless of having events generated by multiple microservices or by a single monolith, then you already have enough to start building your decoupled event-driven Backends-for-Frontends (BFFs) for each of your end-user experiences.

The diagram below presents a high-level view of the architecture and its message flow. Representing the domain publishers on the right, each with its own domain-specific aggregate database; and the BFF subscribers on the left, each with its own user-experience-specific projection database. In the middle, there’s an event bus propagating domain state changes, allowing publishers and subscribers to remain decoupled.

Figure 1. Message flow diagram.

Figure 1. Message flow diagram.

The event-driven BFF solutions described in this blog post rely on a technology-specific API, in addition to the following common components:

  • NoSQL database to store domain projection tables, which also supports Change Data Capture (CDC). Here, we use Amazon DynamoDB – a fast, flexible NoSQL database service for single-digit millisecond performance at any scale.
  • compute-layer to process requests and to integrate the CDC stream with the API. Here, we use AWS Lambda – a serverless, event-driven compute service that lets you run code without thinking about servers or clusters.
  • An authentication and authorization mechanism to protect the API. Here, we use Amazon Cognito – a simple and secure service for user sign-up, sign-in, and access control.

Building an event-driven REST BFF using API Gateway

Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. APIs act as the “front door” for applications to access data, business logic, or functionality from your backend services. Using API Gateway, you can create RESTful APIs and WebSocket APIs that enable real-time two-way communication applications.

The following architecture diagram describes, using Domain-Driven Design (DDD) concepts, how to leverage API Gateway WebSocket APIs to create an event-driven UI for end-users. For a PDF version of this diagram, see this link.

Figure 2. Diagram of RESTful BFF using API Gateway.

Figure 2. Diagram of RESTful BFF using API Gateway.

Implementation steps:

  1. Catch the events from your application with purpose-built BFF event consumers. These are responsible for updating denormalized data projections in Amazon DynamoDB for frontend consumption.
  2. On UI load, frontend clients authenticate with Amazon Cognito, then query the data by invoking the BFF API built with Amazon API Gateway. The data is then fetched in DynamoDB, either directly by API Gateway or via a BFF query handler built with AWS Lambda.
  3. Frontend clients subscribe for any subsequent data changes by connecting to a BFF WebSocket endpoint provided by API Gateway, which triggers the update of the “connected clients” table.
  4. Continue to consume and process all relevant events from your application using the BFF event consumers. These consumers continuously update the denormalized frontend data view in the BFF database in real time.
  5. Subscribe to all events resulting from data changes in the BFF database using Amazon DynamoDB Streams, then register a trigger in AWS Lambda to asynchronously invoke a BFF stream-handler Lambda function when it detects new stream records.
  6. Your BFF stream handler then pushes notifications to clients connected to API Gateway’s WebSockets.
  7. When the change notification from API Gateway is received by the frontend clients, they can refresh the UI content.

Building an event-driven GraphQL BFF using AppSync

We see organizations increasingly choosing to build APIs with GraphQL because it helps them develop applications faster, by giving frontend developers the ability to query multiple databases, microservices, and APIs with a single GraphQL endpoint.

AWS AppSync is a fully managed service that makes it easy to develop GraphQL APIs by handling the heavy lifting of securely connecting to data sources like Amazon DynamoDBAWS Lambda, and more. Once deployed, AWS AppSync automatically scales your GraphQL API execution engine up and down to meet API request volumes. Additionally, AppSync adds caches to improve performance, supports client-side data stores that keep off-line clients in sync, and supports real-time updates via transparent subscriptions over WebSockets.

The following architecture diagram describes, using Domain-Driven Design (DDD) concepts, how to leverage AppSync subscriptions to create an event-driven UI for end-users. For a PDF version of this diagram, see this link.

Figure 3. Diagram of GraphQL BFF using AppSync.

Figure 3. Diagram of GraphQL BFF using AppSync.

Implementation steps:

  1. Catch the events from your application with purpose-built BFF event consumers. These are responsible for keeping a denormalized view of data in Amazon DynamoDB for frontend consumption.
  2. On UI load, frontend clients authenticate with Amazon Cognito, then query the data with GraphQL by invoking the BFF API built with AWS AppSync. The data is then fetched in DynamoDB, either directly by AWS AppSync or via a BFF query handler built with AWS Lambda.
  3. Frontend clients subscribe for any subsequent data changes using AWS AppSync subscriptions over WebSockets.
  4. Continue to consume and process all relevant events from your application using the BFF event consumers. These consumers continuously update the denormalized frontend data view in the BFF database in real-time.
  5. Subscribe to all events resulting from data changes in the BFF database using Amazon DynamoDB Streams, then register a trigger in AWS Lambda to asynchronously invoke a BFF stream-handler Lambda function when it detects new stream records.
  6. Your BFF stream handler then invokes an empty mutation on the AWS AppSync GraphQL schema, purposely created to force the subscription to be triggered, thus sending a notification to clients.
  7. When the change notification from AWS AppSync is received by the frontend clients, they can refresh the UI content.
    AWS AppSync provides a simplified WebSockets experience with real-time data, connections, scalability, fan-out and broadcasting which are all handled by the AWS AppSync service, allowing developers to focus on the application use cases and requirements instead of dealing with the complexity of infrastructure required to manage WebSockets connections at scale.

The AWS Lambda stream handler function in step 6 is triggered by new items being inserted into the Amazon DynamoDB table. It reads these items and updates AWS AppSync, alerting it to the new data. A sample of this code, written in node.js, is available here on GitHub as part of an AWS Sample for deploying AWS AppSync in a multi region setup. The primary functions were extracted and are explained below.

The code below shows the entry point to the Lambda function. It receives an event from DynamoDB, triggered by new data in the stream. For each new entry, if it is data that has been inserted (rather than updated or deleted), it will parse the data and call the executeMutation function.

exports.handler = async(event) => {

  for (let record of event.Records) {
    switch (record.eventName) {
    
      case 'INSERT':
        // Grab the data we need from stream...
        let id = record.dynamodb.Keys.id.S;
        let name = record.dynamodb.NewImage.item.S;
        // ... and then execute the publish mutation
        await executeMutation(id, name);
        break;
        
      default:
        break;
    }
  }
  
  return { message: `Finished processing ${event.Records.length} records` }
}

The code below is the executeMutation function that mutates AWS AppSync with the new data received from the DynamoDB stream. Using the third-party library Axios (a promise-based HTTP client for node.js) it connects to the AppSync API endpoint and posts the mutation.

const executeMutation = async(id, name) => {

  const mutation = {
    query: print(publishItem),
    variables: {
      name: name,
      id: id,
    },
  };

  try {
  
    let response = await axios({
      url: process.env.AppSyncAPIEndpoint,
      method: 'post',
      headers: {
        'x-api-key': process.env.AppSyncAPIKey
      },
      data: JSON.stringify(mutation)
    });
    
  } catch (error) {
    throw error;
  }
};

The mutation is generated using the following GQL code:

const publishItem = gql`
  mutation PublishMutation($name: String!, $id: ID!) {
    publishItemsModel(input: {id: $id, item: $name}) {
      id
      item
    }
  }
`

Conclusion

The BFF pattern refers to having one backend per user experience, instead of having only one general-purpose API backend.

By implementing the BFF pattern in an event-drive architecture, you can improve end-user customer experience on your UI by providing near-real-time visual updates when your microservices raise events about mutations in domain aggregates.

In this blog post, we explained how developers can apply the BFF pattern to their REST and GraphQL APIs to load UI-ready data projections and refresh the UI with event-driven notifications.

You can download the detailed reference architectures in PDF for Amazon API Gateway here and AWS AppSync here.

Design Uplift part VI - Using Tools , AI Co pilot in deisgn and development.

I am giving here complete details of my Linked in post related to using co pilot in generating code and making change quickly. Ref:   Desi...