Back to Blogs

How to Get Your Technical Debt Under Control

Pradeep MishraMar 10, 2022

Talk to an expert

about something you read on this page

Contact an expert
decreasing-bar-graph.png

Unless you live in la-la land with a dream team of developers who write perfect code, it is impossible to avoid technical debt. It is a natural by-product of fast-paced development of any SaaS product.

As developers, we always have to choose between delivering on time and delivering with perfect code. It's a trade-off. In most cases, we choose to deliver on time, with a promise to deal with the byproduct later.

Technical debt also occurs because of reasons such as:

  • Change in technology
  • Development of annual frameworks and libraries
  • Non-maintenance of codebase or libraries
  • Introduction of new product features
  • Addition of a new workforce to an existing project to ship faster
  • Need for frequent releases and pressure of timeline

And so, technical debt accumulates. We can either ignore it until it snowballs into something massive or fix some of it to reduce its impact on current and future development.

I have seen teams try to figure out everything from the beginning so there is no minimum tech debt. But in an environment where delivery time matters, slowing down development could cause companies to lose opportunities or customers to competitors.

It makes more sense to come to peace with the fact that there will always be some technical debt. Acknowledging this and then defining some best practices to manage technical debt effectively can reduce its impact on your product.

10 Ways to Manage Your Technical Debt

1. Opt for Modular and Extensible Architecture

An excellent way to start a new project is by adopting an extensible architecture. This involves accounting for all our current requirements while extending the project to add new features in the future without any rewriting.

Start with identifying the various modules based on their functionalities. Develop each module so it is independent and does not affect the working of other modules. However, all the modules should be loosely coupled. By doing this, you can easily break the project into multiple microservices and scale them individually if the need arises.

2. Develop Only What is Required

To build a product or its modules with more flexibility (or to make the next release easy), developers may load it with extra functionalities. This is only effective if you are sure about the future requirements, which is never the case. These added functionalities build up over time, increasing your technical debt.

3. Plan Your Trade-Offs Carefully

Pick what matters the most. For long-term projects that have a high return on investment, carefully consider the design and implementation and minimize technical debt as much as possible. If delivery is the top priority and efforts to build are low, you can knowingly create some debt you can fix later.

4. Never send POC to production

Before developing a new feature or a product, developers build a proof of concept (POC) to check its feasibility or to convey the idea. If the POC is accepted, the feature is included in the road map.

At times, especially when it is working as expected, it is very tempting to put this POC into production.

However, that is a bad idea. A POC is just what it says: a concept, not a complete solution. While developing a POC, we rarely think of all use cases or scenarios because the focus is on writing the code to get desired results quickly. That code is never meant for production, and writing tests around it usually doesn't work. Most of the time, POCs don’t have proper structures, error handling, data validation or extensibility. Use it as a reference and only deploy a complete production solution.

5. Write Code With Proper Documentation

Good code with proper documentation offers multiple benefits, including quick handoff to others, increased reusability and reduced time to build more on top of your code.

There are two types of documentation: within your code and about your code. Both are equally important.

Some examples of documentation within your code are:

  • Function signature
  • Instructions for users
  • Descriptions explaining confusing or complex pieces of code
  • To-dos for future reconsideration
  • Notes for yourself
  • Comments about recent changes

Examples of documentation about your code include:

  • Readme files
  • APIs reference
  • How-to guides
  • FAQs

6. Request Early Code Freezes

Frequent releases (often with limited resources) are major contributors to the accumulation of technical debt. To meet tight deadlines, developers add hard-coded values or resort to quick fixes in codes. And there are always last-minute requirements or requests for change in functionalities. Over time, these quick fixes lead to performance, stability and functional issues.

A good way to deal with this is to introduce a process for early code freeze, so developers can focus on improving code quality and stability instead of adding code until the last minute.

7. Add Technical Debt in Sprint

Eliminating technical debt all at once is not feasible. Product managers are not likely to commit extensive resources since it adds no direct or immediate value to customers. At the same time, developers want to spend more time developing something concrete, from scratch, instead of reworking on the same code.

But there is a practical way out: Create a healthy backlog of debt items and a road map (with timeline) to replace the code's hard-coded, unoptimized and quick-fix scenarios. Add stories to every sprint so you can fix these debt items gradually and in a more organized way.

8. Version Your Code

Your code will likely change as you add new features to your application. One of the best ways to track and maintain these changes is to version your code.

You can create incremental code through versioning, leave behind some old code, introduce breaking changes through newer versions, give users access to multiple versions and stop support for older versions. All of this is in your control.

Versioning is probably the best process through which your code evolves. It is also the preferred way in the SaaS world to shape (or reshape) your product over time without piling up a lot of baggage from the legacy code.

9. Refactoring is Your Friend

Refactoring is the ultimate weapon in your fight against tech debt. How often you need to refactor the code is up to you, but doing this regularly is essential. Make sure you version your changes while refactoring. This keeps your code organized.

10. Balance is Key

Technical debt is okay as long as it's intentional and strategic and not the result of poor codes and design. As developers, our aim should always be to balance it and cushion its blow to the product.

Share on:

Talk to an expert

about something you read on this page

Contact an expert

Recommended posts

May 23, 2023 | 5 min. read

5 best practices for improving customer satisfaction

Customer satisfaction, a measure of how much a company’s products or services meet or exceed its customer’s expectations, continues to dominate the business world. Customer satisfaction directly correlates with and translates to customer happiness, which is reflected in your business ratings. It is an important metric that helps measure how well a business is meeting the needs and expectations of its customers. Therefore, understanding and enhancing customer satisfaction is critical to ensuring long-term success for your business. Why customer satisfaction mattersWith more than 96% of customers claiming that customer service is essential to brand loyalty, it’s no secret that customer satisfaction is vital for your business's growth. It is the key to keeping your current customers and retaining new ones. Customer satisfaction directly affects customer loyalty, and it affects how customers may intend to associate with your brand in the future.Therefore, it’s crucial to ensure that your customers are happy with your products and services. Customer satisfaction provides insight into things that need improvement or ways to improve your services or product to serve your customers better. A high level of customer satisfaction shows that a business is providing quality products or services, meeting customer expectations and delivering an overall positive experience. In today's digital world, understanding the market from the end user's perspective is the need of the hour. For example, in a product-based SaaS organization, recognizing customer requirements, curating the product according to their needs, and understanding best practices for improving customer satisfaction can help you get an edge over your competitors.Top 5 best practices for improving customer satisfactionSo, what factors affect customer satisfaction? How do you improve it? Understanding what drives customer satisfaction is a must to improve it. Here are the top five best practices for improving customer satisfaction in your SaaS business:Provide convenience with in-app chat featuresConvenience lets customers use your products or services without hassle. There’s comfort in knowing that everything will be taken care of, no matter what.A virtual assistant or chatbot is one way to provide convenient customer service. The in-app product chat feature provides the easiest way for customers to connect with your support team or agent. Customers always look for an easy way to connect quickly with the support team in case they need help while using the product or if they have any feedback about a feature. However, there should not be limitations to reaching out to the support team or agent only via chat support; an email or contact number should be available to expedite the process.Deliver the human touch with personalization Delivering a personalized customer experience helps establish a strong emotional bond with your customers. Research suggests that 80% of customers are more likely to buy products or services from a brand offering them personalized experiences.Providing a human touch or lively experience is essential, which is not the case when implementing a chatbot for answering queries. Customers expect to get the most relevant answers to their queries with little back and forth. Most of the time, organizations implement a chatbot by designing it to provide the most appropriate answers to the questions asked by the customers. However, after a certain point, bots are not self-sufficient to answer these accurately. In such instances, a live customer support agent can interact with the client to gather the required information by probing for correct questions. This gives additional assurance to the client that the team is looking into their query and that they will get a resolution soon.Track response and turnaround times (FRT and TAT)The quicker the response to a customer’s complaint, the better it is for the customer and the business. First Response Time (FRT) and Turn Around Time (TAT) are the most critical factors in engaging customers. First response time (FRT) is a metric used to measure the time it takes for a business to respond to a customer's initial inquiry or request for assistance. For example, this could be a customer support email, phone call, or message on social media.FRT is crucial because it directly impacts customer satisfaction. Customers generally expect a quick response to their inquiries, and delays in response time can lead to frustration and a negative experience. A prompt first response time can help establish trust and build a positive relationship between the customer and the business.When customers reach out to the support team, they expect an initial reply or acknowledgement of their query. A prompt reply or acknowledgement assures customers that the organization is dedicated to understanding their problems and helps win customer trust and improve satisfaction. In customer service, turnaround time (TAT) is often used to measure the time it takes to resolve customer inquiries or complaints. This includes the time it takes to provide a first response (FRT) plus the time it takes to resolve the issue entirely. A low TAT generally indicates that a business can quickly and efficiently resolve customer issues, leading to higher customer satisfaction and loyalty.Organizations should serve customer requests 24/7, across all time zones. It is important to share regular updates on specific cases, so use a unique reference number that can be shared with the client so that they can reach out for updates.Resolving customer-reported bugs in a timely manner helps unblock users and positively affects the organization. Once a bug is resolved and/or an enhancement is implemented, updating customers with a unique reference number is a key factor in improving customer satisfaction. Obtain customer feedback Obtaining customer feedback is essential for enhancing customer satisfaction as it helps businesses gain insight into their customers' needs, preferences and pain points. By acting on this feedback, businesses can make necessary changes to meet customer needs and expectations better, leading to increased satisfaction and loyalty.Feedback helps identify the gaps between customers and businesses. Understanding customer needs via feedback is very important so details can be discussed with the product team to implement them within the current functionality. A transparent approach to customer feedback collection ensures customers are heard, improving their overall experience. Ensure customer success with proper onboarding Earlier in the onboarding process, determining the customer's end goal for using your solution and defining milestones to achieve that goal improves your customer's experience and assures them that they are in the right hands moving forward. Connecting with customers is important. Schedule regular meetings to understand their workflow and hand-holding (when necessary) until they are fully live. This is usually done with dedicated customer success managers and solutions architects assigned to specific customers. It helps them achieve their use case, clear any roadblocks with the product and get technical guidance when needed. CSMs also help clients to expedite resolving the important features or bugs they may experience. A wonderful onboarding experience engages the customers better, making them less likely to churn and more likely to make repeat purchases. Also, a solid onboarding experience makes customers feel valued while increasing their product adoption.Final thoughtsThe right strategies and best practices can help improve customer satisfaction, propelling your SaaS product's trajectory toward reduced churn and increased business revenues. Investing in contemporary customer satisfaction strategies (artificial intelligence, visual tools and an omnichannel approach) enhances your ability to offer personalized experiences. Most importantly, increased customer satisfaction keeps your customers returning and is directly linked to growing your business' topline revenue.

Mar 28, 2023 | 7 min. read

From legacy systems to microservices: Transforming auth architecture

Contentstack receives billions of API requests daily, and every request must be validated to be a valid Contentstack identity. It is a common industry practice to achieve this using some sort of “identity token" for every request. Imagine having multiple types of identity tokens, such as session tokens, OAuth tokens, delivery tokens, management tokens, etc. The problem of securing billions of API requests daily can be challenging. We decided to address this by spinning up a new team that handles the complex problems of user authentication and authorization in a token-agnostic platform.Our transition journey Contentstack started as an API-first headless CMS platform that allowed content managers to create and manage content while simultaneously and independently enabling developers to use Contentstack's delivery API to pull that content and render it to create websites and applications. This means that Contentstack’s traffic increases proportionately to the traffic received by our customers' websites and applications.With increased traffic and usage, we catered to various new use cases by developing new features. These features were powered by a set of microservices, each catering to a particular feature domain and needing support for processing multiple identity tokens that had roles and permissions associated with them. The whole system had turned out to be quite complex, and performing auth had become a great challenge. This prompted us to redesign our auth architecture, which addressed the issues of being a token-agnostic and low-latency platform.Read on to learn more about this journey and how we have been able to:Transition from a monolith to a low latency microservices-based auth (authentication plus authorization) and rate-limiting architecture.Set up centralized authentication for multiple (any domain) microservices that are part of the same Kubernetes cluster.Set up decentralized and self-serviced, policy-based authorization for internal services and teams.Increasing feature sets increased domain microservices, which increased the complexity of performing auth.Monolithic auth architectureMonolithic architectures can be difficult to maintain, scale and deploy. In a monolithic architecture, user authentication and authorization are typically tightly coupled with the application code, making it difficult to implement and maintain robust security measures. Monolithic architectures often rely on a single authentication and authorization mechanism for the entire application, which can limit the flexibility of the system to accommodate different types of users or access levels.Performing auth in a typical monolithic architecture.In monolithic architectures, the steps involved in auth are the following:Users use their credentials at the client to generate a session token or use an existing identity token to generate other identity tokens.Users then use the generated identity token to perform a business operation by making a request to the application server.Once a request is received at the application server, the authentication middleware authenticates the token and forwards the request to the business module.The business module performs the business operation based on the authorization rules applied to the user identity.Problems with monolithic auth architecture:Authentication and authorization logic is mixed with the business logic.Changing the way an identity performs an operation on a resource involves a change in the associated auth-related logic.Each domain individually implements the authorization logic, causing a difference in implementation.Since authorization logic is deeply nested in business logic, we lack visibility into authorization rules applied to a resource.Shipping of new authorization logic requires a fresh deployment of the application image.New microservices require knowledge of various identity tokens and resource authorization rules to be applied.Microservices auth architectureMicroservices offer a more flexible, modular approach that allows for easier maintenance, scalability and deployment. With microservices, each service can be developed, deployed and scaled independently, allowing for faster time-to-market, improved fault tolerance, and better alignment with modern development practices. Additionally, microservices offer more efficient use of resources and better support for diverse technology stacks.AuthenticationWhy centralized authentication?Centralized authentication is a security model in which a central authority manages authentication, such as a server or service, rather than it being distributed across multiple systems or applications. There are several reasons why centralized authentication is commonly used and considered advantageous, including increased security, simplified management, improved user experience and lower costs. While there are some drawbacks to centralized authentication, such as the increased risk of a single point of failure and increased complexity in managing the central authority, the benefits often outweigh the risks. Centralized authentication and rate-limiting at the edge of the service mesh.The steps involved in the centralized authentication process are the following:Any incoming request to the Kubernetes cluster first lands at the Istio ingress gateway.The request containing the identity token is proxied to a central authentication gRPC service with the help of envoyproxy's external authorization filter.The central authentication service queries Redis with the identity token and metadata associated with the request.Redis responds with the identity associated with the token and the current rate-limit count based on the request metadata.The central authentication service responds to Istio with either of the following:Authenticated response with user context attached to the request in the form of request headersUnauthenticated responseRatelimit exceeded responseAn authenticated request containing the user context is then forwarded to the upstream service.Advantages over the monolithic architecture:Easier to onboard newer microservices to central authentication service by using label based istio-injection.All requests are authenticated and rate-limited at the edge of the service mesh, ensuring that each request entering the cluster is always rate-limited and authenticated.The request forwarded to the upstream microservice has user identity context attached to it in the request headers, which can be further used for applying authorization rules.Keeping centralized authentication eliminates the problem of multiple mutations performed by the upstream microservices on the identity of the token.Authorization Centralized authorizationWe tried a model where along with authentication and rate limiting, we also added authorization as a responsibility of the central authentication and rate limiting service. The service would first identify the incoming request’s identity from the token and apply rate limiting based on the request metadata. Once the user identity is known, authorization rules could be applied to the user’s identity, thereby performing the entire Auth at the edge of the service mesh. Problems with this model are the following:This model could only perform basic authorization at the edge based on the request metadata provided, such as validating organizations, stacks, etc. However, it could not perform fine-grained authorization, such as finding out which content types the logged-in user had access to.For RBAC, each domain has its roles and permissions associated with it; performing authorization for such requests requires knowledge of the upstream domain and leads to the addition of domain-specific logic in the centrally managed domain-agnostic platform.With newer domain microservice additions, this again would lead to the problem of lacking visibility into authorization rules applied to a resource.Distributed authorization with central authorization serviceWe then tried implementing a model where we distributed authorization to the upstream microservices where each upstream microservice makes a call to a central authorization service. The authorization service has access to all the roles and permissions of different domains and was able to give appropriate authorization results. Authorization could now be performed from the upstream service’s business module by making a network request using Kubernetes cluster networking to avoid making a call over the internet.Problems with this model are the following:The central authorization service becomes a single point of failure.Any change in the API contract defined by the central authorization service requires all the upstream services to abide by it and makes shipping these changes independently a complex task.Performing authorization adds a network hop, thereby increasing the latency.Distributed authorization with the sidecar patternLearning from the previously discussed disadvantages, we wanted to build a model that had authorization distributed, low latency and made shipping authorization logic an independent activity. ArchitectureThe architecture involves the following components:Auth sidecarCentral policy serviceAuth SDKArchitecture for authorizing an authenticated request with the sidecar pattern.Auth sidecarThe auth sidecar is a gRPC service that gets injected along with the microservice’s application container in the same Kubernetes pod. Let’s understand how this architecture helped us tackle the previously mentioned problems.Single point of failure: The auth sidecar service runs with the application container in the same pod, and any case of failure is only limited to the current pod. Restarting the pod gives us a fresh set of application and auth sidecar containers.Independent delivery: Since the auth sidecar service container is shipped along with the application container, the application service can decide which version of the sidecar image to use, thereby making the delivery of newer versions of the authorization sidecar independent.Low latency: There is no network hop involved in making a gRPC call to the auth sidecar running in the same pod. This helps the application to get the authorization result with very low latency (in a few milliseconds).Updating authorization logic: The auth sidecar periodically downloads fresh policy bundles; any time there is a change in policy bundle coming from the central policy service, the auth sidecar updates its local policy cache with the new bundle.This way, updating authorization logic does not involve a fresh deployment/restart of the application container.Components involved in auth sidecar Responsibilities of the components involved in the authorization sidecar.Aggregator: The responsibility of the aggregator is to fetch authorization-related data for the current identity based on the metadata provided by the application service in the gRPC call. It then aggregates it to be evaluated against the authorization policy.OPA Engine: We use OPA (Open Policy Agent) to periodically download fresh policies and evaluate the policy path mentioned in the gRPC call against the aggregated data.Central policy serviceThe central policy service is a repository of policy bundles (*.rego files) which are independently managed by the domain microservices. The maintainers of the domain microservices create these policies for various resources that need authorization. Since these policies only involve rules, it greatly increases the visibility of authorization rules being applied to a particular resource.Auth SDKThe auth-sdk is an internal library that we developed that helps the developers of upstream microservices to easily communicate with different auth components. It can do the following:Extract user identity and other useful information attached in the request headers by the central authentication serviceDiscover various auth components and streamline communicating with themExpose different helper methods to perform any auth-related activity on behalf of the application serviceRedesigned (new) architecture:Tracing the request lifecycle in our redesigned auth architecture.ConclusionMicroservices-based architectures can help address some of these challenges of monolithic architecture by separating user authentication and authorization into individual services, which can be developed, deployed and maintained independently. This approach can provide greater flexibility, scalability and security for user authentication and authorization.However, it's important to note that transitioning to a microservices-based architecture can also come with some challenges, such as increased complexity and a need for more advanced DevOps practices. Proper planning, implementation and ongoing maintenance are crucial to ensuring a successful transition.

Dec 29, 2022

How React works in a composable architecture

React is a JavaScript library widely frequented by web developers who plan on building composable elements for dynamic interfaces. By default, it is a declarative and flexible framework for altering web and app data without having to refresh the DOM every time.  A React CMS splits the roles of designers and developers, placing them into a front-end or back-end role respectively. React is a collection of designated components used to maintain a structured front end, for performing actions like validating forms, controlling states, arranging layouts and passing in data.  Described as a headless infrastructure, the three main ingredients of a React CMS are React, REST API and GraphQL. These libraries allow you to scale content across many channels and devices by eliminating codebase dependencies that would be prevalent in a traditional CMS environment.   When should you use a React CMS? A React CMS is ideal for editing the elements that users interact with, from buttons to dropdowns on your website. And for organizing larger projects, complex code logic is grouped by matching patterns to help you track the state of apps.  It will update your source code in the DOM to reflect changes in app requirements so the content gets delivered without any compatibility issues. This is achieved by tracking the modified versions of your components to back up your data before the system restarts.  If you prefer something more substantial than drag-and-drop customization, then you should consider getting a React CMS to access native API configurations and code blocks that are fully decoupled from the presentation layer.  This will save you time on having to manually update plugins or extensions, so you can divert resources to creating and deploying the app through its API-based integrations.  Moreover, a React CMS has been shown to improve performance by allocating less memory to track component changes. To get around loading delays, it will use the virtual DOM to render only the assets that are found at the URL.  Instead of receiving just the themes and templates, you have complete control over the content layout for fetching chunks of data from API calls to populate your web pages with the desired elements.  How a React CMS works with APIs to distribute content When React is combined with a CMS, it lets you preview the output of workflows before you publish them onto a page. A React CMS is able to transmit on-demand data between the client and server or even during compilation time, to dictate how objects are rendered on a webpage.  Using a composable model, you can call the API to request information from root directories or databases on the server, dividing your website functionality into closed environments that will not interfere with each other.  From a technical standpoint, React CMSes make it possible to edit visual elements through your site’s HTML, by tying it back to the schema of GraphQL as you fill in the fields or toggle the settings.  It’s also great for patching bugs in your JS bundles that might otherwise lead to delayed page interactions or even downtime on the server. Rather than create a project from scratch, the composable architecture makes it easy to reuse content over multiple channels.  In addition, you can search for third-party integrations on the market to help you build streamlined apps that contribute to the overall React ecosystem. As such, swapping out components is the way to go when your team is pressed for time on the next feature release.  By employing API-first methods, you won’t have to monitor CMS servers or databases in messy clusters, unlike what happens in traditional CMS solutions.  What are the benefits and features of a React CMS? A React CMS ensures the continuous operation of components on the app, giving you composable options to import modules that perform what you need on the client.  Once you understand the fundamental components, it becomes easier to develop and maintain web apps by leveraging just the required functionality to deliver consistent user interactions.  To manage your databases, it utilizes GraphQL to recover queries from the app data in a structured format. As a substitute for REST, GraphQL caches and updates databases with new entries, thereby combining them with Apollo or Axios packages to execute your API requests.  Another aspect is the custom editing experience, which generates dynamic content in an organized manner, so you can avoid a conflict of interest when loading HTML and JSON files in succession.  If you’re looking for a specific feature to implement, such as a login page or shopping cart to enhance the user experience, you can learn about them in detail through the support documentation.  The goal is to stabilize your app’s performance during page loads to improve the accessibility of various media types. To see the CMS in action, you can simply declare the permission and hierarchy of API objects using the default arguments.  But before you map out the visuals, it’s best to have a clearly defined scope of the app by taking measures to scale it in conjunction with your network or server capacity.  Choosing a React CMS to decouple your web services For enterprise workflows, React APIs are a must-have that can shorten the time to market by automatically cleaning content backlogs and preparing for site migrations. Since there are lots of options for React CMSes, you’ll have to narrow down which libraries are capable of handling your app’s payload.  If you want a composable CMS focused on developers, get one that offers a large collection of third-party frameworks or extensions in order to cover all bases of your React app. For example, you may need conditional fields to verify user accounts or support for SQL to join multiple tables containing product details.  Another advantage is being able to override protocol errors or software failures that are detrimental to performance indicators before they end up on the latest build. This ensures development is productive and has room to grow into cross-platform capabilities.  The cost of implementation is well worth it for specialized use cases that cover static site generators, mobile apps and web services. In return, this puts custom assets, webhooks and test scenarios at your fingertips, so you can keep adding integrations with other tools without worrying about the impact on existing code. With headless CMS functionality, you can frame API responses and multiple SaaS solutions around predictable outcomes to close the gap between React and your site content.  Learn more If you would like to learn more about the benefits of a composable architecture, see our article “Why a composable CMS is right for you.”  Schedule a free demo to experience the benefits of a composable CMS with Contentstack’s headless CMS-based digital experience platform.   

Dec 01, 2022

5 things you should know about Next.js

Next.js is a React framework that supports high-performance web applications through a patchwork of modern tools and features. These building blocks will help you develop sleek React apps with scalable infrastructure, numerous integrations, limitless routing and a better user experience. To enhance development, Next.js takes the guesswork out of selecting third-party libraries by delivering front-end UIs for every occasion. If you want to take advantage of interactive layouts, there are React components that can merge static and dynamic page generation into one. Next.js is a React framework that improves how your business operates online:SEO: More organic traffic is always a good thing with increased visibility in the SERPs.  Responsive: Adapts to any device or screen size by skipping CSS selectorsTime to Market: Pre-made components save time on product testing and feedbackVersatile UX: Forget about plugins and templates when you have complete control over visual design.As a standalone JavaScript library, React excels in performance thanks to an abundance of reusable tools. The only problem is rendering web content on the client side. With Next.js, it’s much easier to start your own project, where you no longer have to configure tools or reinvent the wheel. 5 things to know about Next.js1. Data fetching methods: SSG, SSR and ISRRendering converts JavaScript into HTML and moves web resources into the DOM. Data fetching pre-renders and loads your content during build time, with commands for server-side, static-site, client-side and incremental static regeneration. When you’re in a CMS, a pages directory will link each one to a dynamic route, rendering them in advance without dipping into client-side JS. This is done through either static site generation (SSG) or server-side rendering (SSR). SSG caches pages over a CDN by crawling your application to boost SEO rankings. This makes it a versatile page builder for marketing and blogging activities, on top of importing items into the back-end database. You just have to export the getStaticProps function to pass elements onto the client side. SSR detects files on the server and renders their HTML on the client page. It does wonders for user experience by allowing you to use recycled code on a high-speed connection. To fetch page data at the request time, you can call the getServerSideProps function to return the exported JSON for user dashboards or portals. Incremental static regeneration (ISR) differs in that it won’t render the requested page until after the user tries to visit it. The outcome is a pre-rendered version being shown to the user unless another build replaces it or the cache timeout is triggered. ISR assigns static generation to individual pages so you aren’t forced to rebuild the whole site.   2. Build an API with dynamic routesFor those who want to develop their own API, Next.js offers a solution through API routes. How it works: A file in the pages/API directory gets treated as an endpoint deployed to the serverless function. The route comes with an SSG to grab your page data via a headless CMS, and Preview Mode to load a copy of your draft before it gets published. A great use case for API routes is processing user input, mainly for account sign-ups or forms to fill out. A POST request is then transmitted to the API route, thereby saving the fixed entry into your database. Here is the code for creating an API route that passes in the HTTP message and server response: export default function handler(req, res) {res.status(200).json({ text: “Hello World!”});}Inside the brackets, you can return a JSON response with the status code 200 from the local host 3000 URL. Req and res are the handlers that receive either an incoming message or a helper function to fetch the endpoint. Dynamic API routes allow you to establish a REST pattern through subsequent GET requests for getting a list of posts or a media library in one go. It catches all your API paths by matching parameters to the specified queries and mobilizing them to the page. For external API routes, Next.js supports deploying on REST, GraphQL, and CORS headers. GraphQL provides the most use cases for uploading files and defining schemas. 3. Features for editing and handling scriptsEnable Fast RefreshOne neat feature of Next.js is called Fast Refresh because it sends you feedback based on the edits you’ve made to a React component. Enabled on newer versions, Fast Refresh prompts most changes in seconds while preserving a constant state. You have several options to restrict code updates to a particular file and modify its core logic or event handlers at will. On non-React files, it reaches into other imported files and re-runs them with the recent edits. Fast Refresh quickly catches mistakes on your end, to correct syntax and runtime errors even when you don’t reload the app. The previous values are always preserved because of useState and useRef arguments. Resetting the state is done by typing // @refresh reset in the modified file, and remounting the components on every update. Automatic Code SplittingAutomatic code splitting bundles your application into separate pages that are accessible through different URLs, turning them into new entry points. On closer inspection, each page is partitioned into smaller chunks to eliminate dependencies and reduce the number of requests. The point of bundling JavaScript is to contract load times by only running the code on a page once a user lands there. It’s also called on-demand loading because it renders the resources in order of importance.Splitting gets rid of duplicate code on repeat navigations, even though it preloads other pages a user might visit soon. This applies to shared modules or dependencies that you’ve downloaded. The final outcome is a smaller payload size on your React app.4. Manage websites on the Jamstack architectureJamstack has been pivotal in the responsive website scene, ensuring they are secure and adaptable to business needs. It incorporates pre-rendering and decoupling of browser applications by partnering with site generators including Jekyll, Gatsby and Docsify for lightweight editing of HTML markdown on both files and templates. The vast majority of Jamstack sites are used to host personal blogs, B2B products, and e-commerce stores. Some of them are enterprise sites frequented by millions of users with developers working around the clock to keep servers online.  Jamstack technologies are not only available on the client side but are also being implemented on the server side by full-stack developers. Whether it’s leveraging microservices or containers, there are functions that perform every task on your workflow checklist. When merged with CMS platforms, these site generators are bound to drive organic traffic to your website and attract more app users in the long run. 5. Compiles TypeScript for a uniform rendering experienceIf you’re attempting to create a TypeScript project, you won’t need to configure any built-in pages or APIs. In fact, it’s possible to clone the starter simply by calling create-next-app with a typescript flag. Then follow the directions on the command output to create a user profile. To send over an existing project, declare a new tsconfig.json file and save it to the root folder so it carries the default settings. Then it just boils down to toggling the compiler options or setting the file path before you insert an npm run dev to fetch the required packages and finish the setup. Next.js has specific types for Static Generation and SSR you can use to load web content in an asynchronous manner. If you need to migrate the app to TypeScript, import the built-in type AppProps and let it update your .js files to .tsx through the compiler. And lastly, the TypeScript integration supports next.config and incremental type checking to help detect any errors that pop up in your application. Optimize your site performanceWhen building a React app, specialization is the answer to remedying development costs that would exhaust your resources. After you adopt the Next.js framework, installing packages along with making API calls won’t be as complicated anymore. If you’re serious about perfecting the user experience, getting Next.js will optimize your site performance for better visibility on search engines.  The system is packed with exceptional tools for importing JavaScript libraries, designing elegant themes, image rendering and much more. It has everything you need to launch a successful project on React.

Oct 06, 2022

GraphQL vs. REST API: Which is better for querying data?

GraphQL vs. REST API: Which is better for querying data?Choosing the best API for compiling data can seem overwhelming if you don’t know how well they perform on a larger database. Developers typically use them to exchange data between programs and build functionality for their web apps. This makes it possible for the front-end and back-end teams to communicate better and develop products for consumers. The top two APIs are GraphQL and REST, each with its own pros and cons for sending a request and retrieving the result. GraphQL is considered an open-source data query and manipulation language for APIs, whereas REST is defined as an architectural standard for interacting with localized software services. As a developer, you might be curious about the potential use cases of both, as they provide a seamless environment for testing new features. Ultimately, this comes down to the scope of your project and what problems you’re trying to solve. This article will explore how they compare on multiple fronts, from fetching relevant information to sorting entries by category. Properties of REST APIREST diverges from GraphQL in that requests are grouped via endpoints and mutations can have any format besides string. It relies on a GET command to fetch resources (JSON response), which requires making multiple API calls to grab separate search results. Likewise, it is server-driven rather than client-driven architecture stacked into layers of hierarchy. Here are the key features of REST API:Each HTTP status code points to a unique response The server determines the shape and size of resourcesAbility to cache on the browser or server with a CDNHas a uniform interface that decouples the client from the serverPlenty of flexibility since calls are stateless and do not depend on each otherBenefits of REST APIREST works best on media files, hardware or web elements, mapping a linear path to those resources. A REST API will boost its performance by scaling to client demands and is capable of locating resources by name. It is built for storing common data types in memory and can be deployed from several servers in one sitting. With REST API, you get the opportunity to develop apps in all kinds of environments, due to how it integrates with a wide range of frameworks. It has been implemented in languages including Python, Java, PHP, and Ruby, enabling you to perform operations or create object instances explicitly over the protocol. On the bright side, you can easily migrate from one server to the next, or even build a portable UI across platforms and OSes. REST is ideal for automatic HTTP caching, reporting on errors, and has you covered against DDoS attacks. Nonetheless, its simplicity has some merit, being that it’s easy to extend and modify for connecting to other apps or services. Properties of GraphQLOn the other hand, GraphQL overcomes the hurdles presented by REST, as it allows the user to make targeted queries using a POST request. This is directed toward a single URL endpoint and returns the matching result if it exists in the database. GraphQL is instead arranged by schema, so the identity won’t match its fetch method. To validate queries, it will scan the cached metadata, an option not supported by REST. Here are the features that define GraphQL: A self-documenting model that conforms to the client’s graph dataThe server dictates which resources are open to the userReduces overhead communications with API providersSelects the type of operation using a keyword on the schemaA request executes multiple fields that converge at the same endpointAdvantages of GraphQLGraphQL brings many benefits to the table, shaping JSON data into a readable syntax. It expresses more consistency across operating systems, boasting faster development speeds on all platforms. It is capable of decoupling the front end from the back end to encourage work done on independent projects. To drive productivity, front-end iterations are no longer tied to back-end adjustments, placing less burden on the server. It’s also strongly typed, limiting queries to certain data types based on context. This API is designed to help you with query batching and caching by merging SQL queries to prevent a session timeout. You can look at what each function does and create custom requests to meet your users’ needs. In terms of upkeep, GraphQL will sync to updated documents and maintain version control without manual input. One advantage of GraphQL is the removal of excess data to prevent over-fetching on the fields you specify. On the flip side, you could run into under-fetching and not extract enough JSON values from an endpoint. This doesn’t happen on GraphQL because once a query is sent, the server reveals the exact data structure. Examples of When to Use GraphQL GraphQL is suitable for creating cross-platform apps that customers can access on a mobile phone. Its schema is designed for chaining longer query objects on the client side, helping you gain a better understanding of how data is extracted. GraphQL is used to enhance mobile app performance by reducing load times with fewer calls. It expands your API functionality to remedy issues reported on older versions.Schema stitching is quite convenient for modifying the client side since multiple schemas are combined into one to complete a data source. Let’s look at a few sample queries:Type Novel {    id: ID    title: String    genre: Genre    author: Author}Type Genre {    id: ID    published: Date    genres: [“Fantasy”, “Science Fiction”, “Non-Fiction”, “Adventure”, “Mystery”]    novels: [Novel]}While this example describes the fields under a Novel type, it does not give away how the object is fetched from the client. You still have to construct a Query type to access the values of a novel by its author or genre. Many applications require you to add, delete, or update data on the backend. This is achieved by utilizing three types of mutations.  Here is how you declare a mutation:First, use the mutation keyword to create one that resembles a standard query. For each field, it can take any number of arguments. mutation {    rootField(arg1: value1, arg2: value2) {        arg1        arg2    }}This root field passes in two parameters that return a specific output. Next, you’re able to assign different properties to the mutation object which will show up in the server response.Disadvantages of GraphQLGraphQL isn’t without its problems. Its single endpoint lacks caching, which is possible with a GET request, meaning that you have to implement browser caching for non-mutable queries. In some cases, GraphQL mutations can become buried under a flood of data types. Although you can pull up exact queries, you have no say over third-party client behaviors. Search operations like joining queries are more complicated than on REST microservices that route requests over a web host or URL. By default, GraphQL’s rigid queries are difficult to model for advanced aggregations or calculations. As for security, monitoring on GraphQL is practically nonexistent because only a few SaaS contain those API analytics.Examples of When to Use REST API A REST API is your best bet if users need to submit requests as separate URLs to retrieve data from microservices architecture. For projects smaller in scope, you can save memory space by importing its tools on your desired framework to designate unique ids on a handful of calls. If you’re not too fixated on collecting insights or dealing with backward compatibility, REST will do a good enough job. Generally speaking, a REST request comprises of the header, body, endpoint, and HTTP method for managing the standard CRUD operations. To initialize a basic call, you should do the following: response = requests.get(“https://siteurl.com/path.json”)print(response.json())The output to the body section: {    “parameter 1”: “value 1”,    “parameter 2”: “value 2”,    “parameter 3”: “value 3”}A successful request will return code 200 and display the types of fields (strings, integers, dictionaries) stored in that library. REST resources are distinguished by their URLs, which are recovered by delivering JSON to the server (i.e. GET, POST). To illustrate, we will perform an API call that reaches the endpoint of a user profile. Let’s jump into posting JSON to the server:{    “Id”: 529387,    “Name”: {        “First”: “John”,        “Last”: “Brown”    },    “Age”: 24,    “Occupation”: “Research Associate” }In the above example, a response returns the output of an employee who works at a biotech company. To update these fields, you also need to set the MIME type for the body to application/json. Drawbacks of REST APIAfter mobile’s rise to popularity, REST was deemed too inflexible to address network issues. Simply put, it struggled to convert app data to a graphical form by attempting to scale its unstructured parameters. If you want to grab a specific attribute, you have no choice but to create new resources and modify them across multiple roundtrips. Because REST is server-driven, clients are entirely dependent on network conditions. It often leads to nested N+1 queries, chaining API calls on the client, and making the returned URI harder to read. It introduces delays in the development lifecycle where front-end teams must wait for back-end teams to deliver the API, thereby pushing back product release dates. ConclusionThe main takeaway from all this is that GraphQL and REST API serve different purposes in the app development lifecycle. GraphQL gives the data you’re looking for without over- or under-fetching and is compatible with advanced techniques like transforming fields into different values. REST is easier to implement on JS frameworks if you plan to locate a precise resource or design an interactive website.An important thing to remember is they both have advantages and disadvantages depending on the product specifications as well as the user requirements. GraphQL may have the upper hand in an agile environment, but it still has room for improvement. REST has more existing tools and integrations; however, it can be affected by poor network conditions.