# :mage: Empowering Control with Edge Computing
In the ever-evolving landscape of content delivery networks, we understand the importance of giving our customers the right tools they need to be more autonomous in their operations. Until now, our platform has primarily relied on a fixed set of configurations through our API, providing valuable services within a constrained framework. At CDN77, we understand that each customer is as unique as their business needs, so we allow you to go even beyond standard setup with the help of our Support Team.
Today, we're excited to introduce a significant advancement that puts the power squarely in your hands. We're thrilled to introduce our latest offering: **CDN77's Edge Computing**.
Building upon standard solutions, this platform allows you to customize online interactions according to your business and technical objectives, ensuring performance and security. We aim to empower our customers with complete control over how our edge servers transform, cached, and handle HTTP requests.
In this blog post, we'll explore how CDN77's Edge Computing stands to refine your interaction with our CDN infrastructure, granting you unprecedented authority over your data. Welcome to a tailored digital future shaped just for you, by you.
## :fire: CDN Infrastructure & Motivation
As we specialize in content delivery, we heavily depend on our infrastructure.
We operate thousands of edge servers running across the globe. This infrastructure is then supported by a 120 Tbps network with a global backbone.
It's no secret that our edge servers are powered by a tailored version of [Nginx](https://nginx.com) enhanced with [OpenResty](https://openresty.org/). This dynamic combination empowers our servers to store and deliver content efficiently. It offers advanced customization capabilities through real-time manipulation of HTTP requests and responses, ensuring optimal performance and tailored content delivery for every user.
Through our [client section](https://client.cdn77.com/) or an [extensive API](https://client.cdn77.com/support/api-reference/v3/introduction), we offer setting up various features, rules and basic request manipulation. These configurations are then propagated to our edge servers and executed when needed. These configs' technical implementation usually combines Lua scripts and Nginx configurations.
For customers that need more advanced and tailored configuration, that is not generally available from our API, we have a Support Team that can configure almost any request or routing transformation.
While our API cover most of the common cases of HTTP request transformation, we wanted to offer more. Our customers know what is best for them and should be allowed to manipulate their requests however they want, whenever they want, in a secure and isolated manner. Essentially, we wanted to give them full autonomy in what they can do themselves and let them see and debug routing changes instantly. That's why we had to go beyond manual creation of tailored configuration and why we built our Edge Computing platform.
## :rocket: CDN77 Edge Computing
Our focus in designing the Edge Computing platform was to be able to transform requests securely and dynamically. Moreover, we needed to load new modifications and plugins dynamically on the fly without influencing or slowing down anything else running on our edge servers. Additionally, we wanted our plugins to work and smoothly integrate with Nginx, allowing us to adjust virtually any internal behavior as needed.
Another goal was to be able to express any business logic that the customers would ever need. Therefore, we want to be able to execute actual code and not only to be limited by basic grammar and expression. However, this decision brought us a challenge - how to execute untrusted code safely without compromising the security of our servers.
### :oncoming_police_car: Running Untrusted Code
**Running untrusted code** in trusted environment is **hard**.
Ensuring proper isolation and sandboxing mechanisms to prevent unauthorized access to system resources, like files, network, or customer data, demands meticulous attention to detail and can be complex to implement effectively. Moreover, we need to be running untrusted code ***fast***.
When designing our platform, we considered using containers, isolated processes, or even [microVMs](https://firecracker-microvm.github.io/). We found isolated processes to be not safe enough for our use case. MicroVMs, on the other hand, bring other challenges like long cold starts and fast communication between plugins and our Nginx.
The correct answer for our use case laid in the binary world - [WebAssembly](https://webassembly.org/).
### :building_construction: WebAssembly
WebAssembly (Wasm) is an ideal choice for executing untrusted code on servers due to its sandboxed and efficient design. Wasm provides a low-level binary instruction format that can be executed near-native speed, ensuring high performance for diverse workloads. Its sandboxing mechanism employs a secure execution environment that isolates untrusted code from the host system, mitigating potential security risks and preventing unauthorized access to resources.
Wasm's architecture is platform-independent, enabling code portability across different servers and platforms. Combining performance, security, and portability, Wasm ensures that untrusted code can be executed reliably and efficiently within a controlled sandbox virtually anywhere.
As a portable format, one *only* needs a Wasm runtime to execute Wasm plugins. After extensive research, we decided to use [Wasmtime](https://github.com/bytecodealliance/wasmtime) as our runtime. It is written in Rust (:heart:), battle-tested, and can be embedded in an already running process.
### :national_park: Running WebAssembly in Nginx
One of the many metrics used to measure the performance of the CDN is latency and response time.
While building our Edge Computing platform, the main objective was to keep these metrics up and not to increase the general infrastructure load. To do that, we decided to run Edge Computing plugins as close as possible to the infrastructure edge, in the first place, that can understand L7 data (HTTP) and process it.
That's one of the reasons why we decided to embed Wasmtime directly into our Nginx. Nginx Workers processes can now load and execute Wasm plugins and utilize the full power of Wasmtime while keeping the communication overhead between the plugin and the Nginx close to zero.
### :crab: Examples
Let's explore some examples in Rust. These are the plugins or their variants we've been using and deploying to production for some time.
1. Add header `X-Hello: World` to the response headers.
```rust
on_response_headers! {self {
self.add_response_header("X-Hello", "World")
}}
```
2. Select different origin servers for the URLs ending with `.png`
```rust
on_select_upstream! {self {
if let Some(path) = self.get_path() {
self.set_upstream(
if path.ends_with(".png") {
"191.231.167.128"
} else {
"123.234.221.213"
}
, 80);
}
}}
```
3. Protect resource with static secret token loaded from `X-Token` header. Using any token format and performing any required cryptography verifications is possible, so feel free to check the signatures.
```Rust
plugin!(
secret_token: String,
// read configuration and store it without modification to secret_token
|conf: String| -> String { conf },
self {
match self.get_request_header("X-Token") {
Some(token) if token.eq(self.secret_token.as_ref()) => {
// token matches, allow request
}
_ => {
// no or wrong token
self.send_response(
403,
vec![("X-Err", "Auth required")],
Some("Valid token required.".as_ref()))
}
}
}
);
```
4. Block specific URLs by returning `403`. Build `HashSet` from configuration during plugin initialization to save time.
```Rust
plugin!(
black_list: HashSet<String>,
|conf: String| -> HashSet<String> {
// each line in the configuration is one URL
// this is executed only once during plugin initialization
conf.split('\n').map(|s| s.to_owned()).collect()
},
self {
if let Some(path) = self.get_path() {
if self.black_list.contains(&path) {
self.send_response(403, vec![], None);
}
}
}
);
```
5. Set different `Cache-Control` header for service workers.
```Rust
on_response_headers! {self {
if let Some(path) = self.get_path() {
let cache_control =
if path.ends_with("service-worker.js") {
"max-age=0"
} else {
"public, max-age=0, s-maxage=31536000"
};
self.set_response_header("Cache-Control", Some(cache_control));
}
}}
```
6. Directly respond to the requests.
```Rust
plugin!(
greeting: String,
|conf: String| -> String { conf },
self {
self.send_response(
200,
vec![("Content-Type", "application/json")],
Some(format!("{{ \"hello\": \"{}\" }}", self.greeting).as_ref())
)
}
);
```
These are just our examples. You can run virtually any logic that you and your business need. Feel free to utilize the power of thousands of our edge servers and their proximity to the end users.
## :airplane_departure: Beta Program
We've been heavily testing Edge Computing internally and with selected customers for almost a year. We served billions of requests and terabytes of traffic through this platform.
In fact, this very site was served to you by one of our edge computing plugins.
As we're confident in our newest offering, we're launching beta access to our edge computing platform. If you're interested, don't hesitate to get in touch with your customer representative or **sales@cdn77.com**.
## :rocket: Looking Into the Future
As we journey into the future of web services and content delivery, CDN77's new Edge Computing platform is set to evolve and expand, bringing more power and flexibility to developers and businesses alike. With a strong foundation already in place, the following features are under active development and will be available soon to the beta testers.
#### :file_cabinet: Persistent Distributed Storage
Because any generic computing platform needs to be able to persist data, we're working on distributed, eventually consistent key-value storage and distributed SQLite database. Persistent distributed storage is currently our priority number one.
#### :hammer: SDKs, SDKs, SDKs...
We currently have a feature-complete SDK for Rust, Golang, and AssemblyScript. JavaScript and Typescript SDKs are still in their infancy, but we plan to open and publish them shortly.
Eventually, we plan to deliver even more SDKs for Wasm-enabled languages to make it easy for developers to deploy to our platform using language they're familiar with.
#### :bird: HTTP Requests
Our Edge Computing platform was designed to manipulate requests coming to our CDN. However, in the future, we will allow you to dispatch HTTP requests as well.
#### :lower_left_paintbrush: Server Side Rendering
As we're running extensive infrastructure globally, we want to allow our customers to utilize it even more than we do now. One of the ways we're planning to do that is to provide support for server-side rendering frameworks such as [Next.js](https://nextjs.org/), [Nuxt](https://nuxt.com/), or [SvelteKit](https://kit.svelte.dev/).
## :100: Edge Computing
In this blog post, we introduced our new Edge Computing platform that allows you to deploy WebAssembly plugins to our infrastructure. And today, we're launching a beta access program. So, if this caught your eye, let us know what you think and how you would use this platform for your specific case. If you're interested in more technical aspects of the platform, feel free to chat directly with the platform architect [Lukas](mailto:lukas.forst@cdn77.com).
Stay tuned as we will follow on this blog post with a series of more technical deep dives into how we designed and built this platform in the upcoming months.
We're also hiring and looking for developers to help make this platform even more remarkable - check out our [job openings](https://www.cdn77.jobs/).