Delivering personalized content with Netlify’s Next.js Advanced Middleware and Fauna
Tags: netlify, fauna, database, nextjs
Published: 2022-10-26 14:10:27

It’s become a truism that the speed and performance of web applications, e-commerce sites, and websites are critical variables in converting visitors to paying customers. Modern consumers expect these assets to serve data quickly, accurately, and contextually. API-first platforms like Fauna and [Netlify](https://www.netlify.com), paired with other composable technologies designed for distributed workloads, drastically simplify the process of deploying applications that serve dynamic content at the edge with low latency, without complicated stitching or multi-team engineering efforts.

## Serving globally distributed data in legacy architectures
Historically, developers have been constrained in how they optimize the performance attributes and experience of their applications by the underlying infrastructure - typically centralized servers and databases. The emergence of [content delivery networks](https://en.wikipedia.org/wiki/Content_delivery_network) (CDNs) in the early 2000s enabled companies to host and distribute static assets to a globally distributed audience with low latency - however these CDNs were limited to hosting static content like images, text files, and HTML files. As these CDNs were globally distributed, the performance attributes of this static content was far superior to relying on a more traditional centralized model - a user accessing a static site in Shanghai would access that content from the CDN node in Shanghai, instead of being pushed to a data center across the county. With that said, the benefits of serving static content through a CDN wasn’t extended to dynamic content that could change over time and evolve; this category of content relies on compute and data services to transform the data based on context.

In the case of a global or even regional application, relying on a centralized architecture to serve dynamic content can be suboptimal. Consider an e-commerce application with users visiting the site from Los Angeles and Toronto. In an ideal world, the application would serve content that’s unique to those users and may change depending on context - where the user is physically located (and the potential discounts or prompts subsequently served to the user’s location), or if the user came from a referring source, for example. This data is ephemeral and dynamic in nature, and unique to each independent user accessing the application. If a user in Los Angeles is being served data hosted in the US-East 1 data center in Virginia, the performance attributes will suffer as a result simply due to the physical distance between the user and the compute. Similar to static content with CDNs, we want to optimize for speed and performance by moving the processing elements as close to each respective user as possible. This means pushing the compute and data out to the edge.

## Dynamic personalization at the edge
Personalization allows companies to serve information that’s tailored for a particular customer based on a defined set of characteristics (most commonly geo-based). For example, if a visitor on an e-commerce site is based in Seattle, they may be served a discount on an item based on an inventory surplus in a local warehouse. Being able to serve this type of dynamic data, however, is not trivial. The ability to move the compute and data for dynamic content as close as possible to users (as demonstrated in CDNs) was until very recently impossible; this has changed with the emergence of platforms like Fauna and Netlify. 

With [Next.js Advanced Middleware](https://www.netlify.com/blog/nextjs-advanced-middleware-better-runtime-that-extends-nextjs/) (powered by [Netlify Edge Functions](https://docs.netlify.com/edge-functions/overview/)) and Fauna’s distributed-by-default [document-relational](https://fauna.com/blog/what-is-a-document-relational-database?utm_source=Devto&utm_medium=referral&utm_campaign=DevTo_FaunaNetlify) database, we’re able to move servers and databases closer to user locations - similar to the shift we’ve witnessed with static assets served on CDNs, but now for dynamic content. Together, Fauna and Netlify enable a transformation in the application architecture for personalization at the edge: developers now have the option to host business logic wherever it’s most performant. 

When a user writes to or reads from a node, Netlify Edge Functions, the images/CSS files, and pieces of business logic are being grabbed from the closest possible compute node and corresponding data source node. Further, with the power of Fauna’s [user-defined functions](https://docs.fauna.com/fauna/current/learn/understanding/user_defined_functions?utm_source=Devto&utm_medium=referral&utm_campaign=DevTo_FaunaNetlify) and advanced querying, you’re able to access a new mental model that allows you to make strategic decisions on where and how often work needs to be done; if you’re able to move the processing further back in the stack with Fauna, you can build it into the places that have the tightest relationships with the data and be optimized in ways that client-side JavaScript can’t be.

While the middleware component of Next.js is germane to Next.js, out-of-the-box it is limited to redirects or rewrites (you can send users to another page, or proxy other content into the application and show users new content). Netlify has extended the middleware API to give access to the full request, which allows for full transformation and personalization - whether it’s location or referral based. With a proxy or a redirect, you’d need to develop a custom page for each redirect. The ability to do a direct transformation with Netlify ultimately makes the engineering far less cumbersome. Netlify provides a really good example of the power of page transformations [here](https://www.netlify.com/blog/rewrite-html-transform-page-props-in-nextjs/).

## Why Fauna + Netlify for edge personalization

Fauna is delivered as a global API and is complementary to Netlify’s Edge Functions; ultimately, you don’t want to bloat your edge functions with code. Everything in the Fauna-Netlify architecture is server-side rendered, so it creates a faster experience by avoiding bloated client-side code that would flood the client CPU or the browser memory. You’re able to modify your code from being a large response down to the few lines you need to write to account for personalization, and it’s possible to do this in the edge function instead of the client-side without client-side impact to the user and without sacrificing performance. Until very recently, this type of architecture wasn’t possible to build, especially for small teams. With Fauna and Netlify, you can get up and running with a working solution within hours. 

Companies would historically need DevOps, frontend, backend, and database management teams to handle the orchestration of all of the elements associated with a global application. Now, a single full-stack developer can handle all of these elements and sketch out an application in a matter of hours that has global deployment, global database replication, and all of the front end and back end configured. Fauna’s auto-replication, distribution-by-default, and serverless attributes paired with Netlify’s edge compute make it possible. There’s no need to account for sharding, provisioning, or global replication - it’s all delivered out-of-the-box.

## Netlify Edge Functions + Fauna example and code walk-through

To move out of the abstract and into a real-world example, we hosted a webinar with Netlify where we did a code walk-through of a basic marketing site pushed to the edge on Fauna and Netlify. Check out the [accompanying webinar](https://www.youtube.com/watch?v=X5uesJKkbh8) and start digging into the code in the [repo](https://github.com/Shadid12/netlify-edge) to learn how to build the functionality with just a few lines of code. You’ll see that in this example, one user is making a request to the site from Toronto, Canada, and another from Portland, Oregon. When each respective user makes a request, they hit the compute node closest to their respective locations and each is served a unique page. Meanwhile, the request is also directed to the nearest Fauna replica to read and serve the data. In this example, the read is modified at the edge and as close as possible to the user - which wouldn’t be possible with a regionally hosted database or server. Both the compute and data is at the edge - which ultimately reduces latency.

## Getting started
Fauna and Netlify unlock the ability to optimize for the most performant architectural decision based on the use case a team might be trying to solve, instead of being limited to whatever your legacy infrastructure may dictate.

Are you ready to get started?

1. [Sign up for a free Fauna account](https://app.fauna.com/sign-up?utm_source=Devto&utm_medium=referral&utm_campaign=DevTo_FaunaNetlify)
2. Grab your [Fauna API key](https://dashboard.fauna.com/db/keys?utm_source=Devto&utm_medium=referral&utm_campaign=DevTo_FaunaNetlify)
3. Click the [Deploy to Netlify button](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example)

Have any questions or want to engage with the Fauna and Netlify communities? Reach out in the Fauna [Discord channel](https://discord.gg/NHwJFdG2B2) or Fauna [community forum](https://forums.fauna.com/c/help-general?utm_source=Devto&utm_medium=referral&utm_campaign=DevTo_FaunaNetlify), and also check out the [Netlify Community Forums](https://answers.netlify.com).