# Migrate from Cloudflare to Azion | Full Guide

import Tabs from '~/components/tabs/Tabs'
import Code from '~/components/Code/Code.astro'


A platform migration usually begins long before the first configuration file is changed. It starts when a team notices that its current environment no longer gives the same level of clarity, speed, or control it once did.

Maybe deployments still work, but the process requires too much manual coordination. Maybe the application has grown beyond the original architecture. Maybe the team needs stronger compliance alignment, more predictable runtime behavior, or a more unified way to manage compute, storage, databases, delivery, and security.

For teams currently using Cloudflare Pages, Workers, Workers KV, R2, D1, redirects, custom headers, DNS, WAF, logs, or analytics, Azion provides equivalent capabilities through Applications, Functions, KV Store, Object Storage, SQL Database, Rules Engine, Edge DNS, Web Application Firewall, Real-Time Events, and Real-Time Metrics.

The strongest reason to migrate is not simply to replace one vendor with another. It is to modernize your application platform without restarting your architecture from zero.

## How Cloudflare to Azion Migration Works

Traditional platform migrations often require rewriting application logic, reconfiguring infrastructure from scratch, and managing multiple disconnected services. This approach creates operational risk, extends timelines, and fragments team knowledge across different configuration patterns.

![Stack Migration Path](/assets/docs/images/uploads/cf-to-azion.png)

The Azion migration approach preserves your application logic while transitioning to a unified platform:

1. **Incremental migration path.** Start with a single project, validate each layer independently, and expand with confidence. No need to migrate everything at once.

2. **Preserved application logic.** Functions, redirects, headers, and data services map directly to Azion equivalents with minimal code changes—primarily syntax updates for environment access and service imports.

3. **Unified platform model.** Instead of managing compute, storage, databases, security, and observability as disconnected layers, Azion brings these capabilities together with consistent APIs and configuration patterns.

## Feature Mapping

The following table provides a comprehensive mapping of Cloudflare products to their Azion equivalents. A dash (`-`) indicates that Azion does not currently offer a direct equivalent.

| Cloudflare Product | Description | Azion Equivalent Product(s) |
| :----------------- | :---------- | :-------------------------- |
| **Agents** | Build AI-powered agents on Cloudflare's developer platform. | AI Inference + Functions |
| **AI Crawl Control** | Analyze and control AI crawler access to your site. | Firewall + Network Shield + Functions |
| **AI Gateway** | Observe, cache, rate limit, and control AI application traffic. | Functions + Cache + Real-Time Events + Data Stream |
| **AI Search** | Managed retrieval and search pipelines for AI applications. | SQL Database + AI Inference |
| **Analytics** | Analytics products and observability across Cloudflare services. | Real-Time Metrics + Real-Time Events + Data Stream + Edge Pulse |
| **API Shield** | Protect APIs with discovery, schema validation, mTLS, and controls. | Firewall + Web Application Firewall + Network Shield + Certificate Manager |
| **Bots** | Detect, manage, and mitigate automated/bot traffic. | Bot Manager + Bot Manager Lite |
| **Cache** | Configure Cloudflare CDN caching behavior. | Cache + Tiered Cache |
| **Cloudflare for Platforms** | Build platforms on top of Cloudflare services. | Console Kit + Azion API + Marketplace |
| **Cloudflare Images** | Store, resize, optimize, and deliver images. | Image Processor |
| **Cloudflare Network Firewall** | Firewall-as-a-service for network traffic. | Firewall + Network Shield |
| **D1** | Serverless SQL database built on SQLite. | SQL Database |
| **DDoS Protection** | Protect applications and networks from DDoS attacks. | DDoS Protection + DDoS Mitigation |
| **Digital Experience Monitoring** | Monitor user, device, network, and application experience. | Edge Pulse + Real-Time Metrics |
| **DNS** | Authoritative DNS management and DNS security. | Edge DNS |
| **Dynamic Workers** | Spin up isolated Workers on demand for code execution. | Functions |
| **KV** | Global, low-latency key-value storage. | KV Store |
| **Load Balancing** | Distribute traffic across origins with health checks and steering. | Load Balancer + Edge DNS |
| **Logs** | Export, query, and manage Cloudflare logs. | Real-Time Events + Data Stream |
| **Origin Rules** | Rewrite origin settings and route requests to origins. | Applications + Load Balancer |
| **Pages** | Deploy frontend and full-stack applications. | Applications + Azion CLI |
| **R2** | S3-compatible object storage with no egress fees. | Object Storage |
| **Rate limiting** | Protect applications by limiting request rates. | Firewall + Functions |
| **Rules** | Ruleset engine for request, routing, cache, transform, and security logic. | Applications + Firewall + Functions |
| **Secrets Store** | Manage secrets for Cloudflare developer workloads. | Variables |
| **Smart Shield** | Shield and optimize origin access patterns. | Cache + Tiered Cache + Application Accelerator |
| **SSL/TLS** | Manage certificates, encryption modes, and TLS settings. | Certificate Manager + Edge DNS |
| **Terraform** | Manage Cloudflare resources with Terraform. | Terraform Provider |
| **Transform Rules** | Modify requests and responses at Cloudflare's edge. | Applications + Rules Engine + Functions |
| **Vectorize** | Vector database for embeddings and semantic search. | SQL Database |
| **WAF** | Web Application Firewall rules and protections. | Web Application Firewall |
| **Workers** | Serverless compute on Cloudflare's global network. | Functions |
| **Workers AI** | Run AI inference on Cloudflare's GPU-backed infrastructure. | AI Inference |

¹ Orchestrator includes Edge Services and Edge Node as integrated modules for orchestrating containerized workloads on private edge infrastructure.

² Functions can be instantiated within Firewall to transform requests and responses at the edge.

## Migration Strategy

The migration is organized around Azion's four product categories, allowing teams to plan and execute each layer independently:

- **Build**: deploy applications, configure builds and environment variables, migrate Functions, routing, headers, load balancing, cache, image optimization, and AI workloads.
- **Secure**: migrate custom domains, DNS, SSL/TLS certificates, WAF, DDoS protection, bot management, and rate limiting.
- **Store**: migrate key-value data, object storage, and SQL databases.
- **Observe**: migrate analytics, metrics, and logs to Azion's real-time observability stack.

:::note
If you do not need near-zero downtime, you can migrate in phases with maintenance windows. This allows stopping writes during each migration step without requiring parallel data synchronization.
:::

## Build

The Build category covers application deployment, compute, routing, and configuration. Start here to bring your application onto Azion and establish the foundation for the rest of the migration.

### 1. Project Setup on Azion

The first step brings your application into Azion in a way that feels familiar to teams that deploy modern web projects. If you have used Cloudflare Pages, you already understand the pattern: connect a repository, define framework settings, run a build, deploy the output, and validate the generated URL.

Azion follows a similar workflow but with a broader platform context. Your project becomes part of an environment where application delivery, Functions, rules, security, and observability can be managed together.

#### Key Differences

| Aspect | Cloudflare | Azion |
| :----- | :--------- | :---- |
| **Config file** | `wrangler.toml` (TOML) | `azion.config.js` (JavaScript) |
| **Framework detection** | 15+ frameworks | 20+ frameworks with auto-detection |
| **Cold starts** | Possible | Minimized |
| **Compliance** | SOC 2, ISO 27001 | PCI DSS 4.0.1 Level 1, SOC 2 Type II |

#### Connect Your Repository

1. Open [Azion Console](https://console.azion.com/).
2. Click **+ Create** > **Import from GitHub**.
3. Authorize the Azion GitHub App.
4. Select the repository you want to migrate.

:::note
Keep the first deployment intentionally small. Do not try to migrate every domain, redirect, function, storage dependency, and database at once. Start by proving the application can build and run on Azion.
:::

#### Configure Your Build

Azion auto-detects your framework and configures build settings. Override the detected preset in `azion.config.js`:

<Code lang="javascript" code={`
import { defineConfig } from 'azion'

export default defineConfig({
  name: 'my-project',
  preset: 'nextjs', // Override auto-detection if needed
})
`} />

#### Deploy and Verify

Deploy from the Azion Console or CLI. Your temporary Azion URL follows this pattern:

<Code lang="text" code={`
https://xxxxxxxxxx.map.azionedge.net/
`} />

Validate the deployment:

<Code lang="bash" code={`
curl https://xxxxxxxxxx.map.azionedge.net/
`} />

#### Reference documentation

* [Applications](https://www.azion.com/en/documentation/products/build/applications/)
* [Applications first steps](https://www.azion.com/en/documentation/products/build/applications/first-steps/)
* [Azion CLI overview](https://www.azion.com/en/documentation/products/azion-cli/overview/)
* [Import an existing project from GitHub](https://www.azion.com/en/documentation/products/guides/import-an-existing-project-from-github/)

### 2. Converting Build Configuration

A migration can appear successful when the build passes but fail later when runtime behavior differs. Review build and deployment configuration carefully instead of treating it as a mechanical command replacement.

#### CLI Quick Reference

| Task | Cloudflare | Azion |
| :--- | :--------- | :---- |
| **Install** | `npm i -D wrangler@latest` | `curl -fsSL https://cli.azion.app/install.sh \| bash` |
| **Login** | `npx wrangler login` | `azion login` |
| **Local dev** | `npx wrangler pages dev ./dist` | `azion dev` |
| **Deploy** | `npx wrangler pages deploy ./dist` | `azion deploy` |

#### Reference documentation

* [Azion CLI overview](https://www.azion.com/en/documentation/products/azion-cli/overview/)
* [azion.config.js reference](https://www.azion.com/en/documentation/devtools/cli/configs/azion-config-js/)
* [azion deploy command](https://www.azion.com/en/documentation/devtools/cli/deploy/)

### 3. Migrating Environment Variables

Environment variables contain API keys, database credentials, authentication secrets, service endpoints, feature flags, and environment-specific configuration. Migrating them incorrectly causes runtime failures even when deployment succeeds.

#### Key Differences

| Aspect | Cloudflare | Azion |
| :----- | :--------- | :---- |
| **Access** | `env.VARIABLE` | `Azion.env.get('VARIABLE')` |
| **Parameters** | `fetch(request, env, ctx)` | `fetch(request)` |

#### Evaluate Your Variables

Before changing code, identify every variable in:

* Cloudflare Pages: **Dashboard > Settings > Environment variables**
* Cloudflare Workers: `wrangler.toml`
* CLI-managed secrets
* CI/CD environment settings
* Runtime configuration in source code

#### Create Variables in Azion

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Navigate to **Build > Variables**.
3. Click **Add Variable**.
4. Enter the variable name and value.
5. Click **Save**.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
curl -X POST 'https://api.azionapi.net/variables' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
  "key": "key-test",
  "value": "value-test"
}'
`} />
:::note
Azion manages environment variables at the Function instance level, not through a standalone variables API. Variables are configured as key-value pairs in the `vars` field when creating or updating a function instance. See the [Functions Instances documentation](https://www.azion.com/en/documentation/products/build/applications/functions-instances/) for details.
:::
</Fragment>
</Tabs>

#### Update Your Code

<Code lang="javascript" code={`
// Before: Cloudflare
const apiKey = env.API_KEY;

// After: Azion
const apiKey = Azion.env.get('API_KEY');
`} />

:::caution[warning]
Avoid copying secrets into local notes, tickets, chat messages, or temporary documents. Keep secrets in approved systems and limit access to processes that need them.
:::

#### Reference documentation

* [Environment Variables](https://www.azion.com/en/documentation/products/build/develop-with-azion/environment-variables/)
* [Working with variables](https://www.azion.com/en/documentation/products/guides/deploy/work-with-variables/)
* [Azion runtime environment variables reference](https://www.azion.com/en/documentation/products/functions/environment-variables/)

### 4. Migrating Rewrite and Redirect URLs

Redirects protect years of SEO value, campaign links, backlinks, bookmarks, and user expectations. When redirects break, the impact shows up as lost traffic, lower rankings, and poor user experience.

#### Key Differences

| Aspect | Cloudflare | Azion |
| :----- | :--------- | :---- |
| **Configuration** | `_redirects` file | Rules Engine (Console or API) |
| **Pattern matching** | Glob patterns (`/*`) | Regex (`^/.*$`) |
| **Capture groups** | `:splat`, `:placeholder` | `%{capture[1]}`, `%{capture[2]}` |

#### Pattern Conversion

| Cloudflare Pattern | Azion Regex |
| :----------------- | :---------- |
| `/old-page` | `^/old-page$` |
| `/blog/*` | `^/blog/(.*)$` |
| `:splat` | `%{capture[1]}` |

#### Create Redirect Rules

Navigate to **Rules Engine** and configure:

**Criteria:**

<Code lang="text" code={`
\${uri} matches ^/old-blog/(.*)\$
`} />

**Behavior:**

<Code lang="text" code={`
Redirect To (301): /blog/%{capture[1]}
`} />

#### Verify Redirects

<Code lang="bash" code={`
curl -I https://yourdomain.com/old-blog/post
`} />

:::note
For SEO-sensitive migrations: prioritize permanent redirects where appropriate, avoid unnecessary redirect chains, confirm canonical paths remain consistent, and test both trailing slash versions when relevant.
:::

#### Reference documentation

* [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/)
* [Rules Engine variables and operators](https://www.azion.com/en/documentation/products/build/applications/rules-engine/#variables)
* [Applications reference](https://www.azion.com/en/documentation/products/build/applications/)

### 5. Migrating Custom Headers

HTTP headers control caching, security, and browser behavior. Azion gives teams a more flexible model through `azion.config.js` and Rules Engine, allowing rules that respond to request characteristics.

#### Key Differences

| Aspect | Cloudflare | Azion |
| :----- | :--------- | :---- |
| **Config file** | `_headers` (text) | `azion.config.js` (JavaScript) |
| **Phases** | Response only | Request and response |
| **Dynamic values** | Not supported | `${uri}`, `${host}`, `${geoip_city_country_code}` |

#### Example: Security Headers

<Code lang="javascript" code={`
import type { AzionConfig } from 'azion/config';

const config: AzionConfig = {
  applications: [{
    name: 'my-app',
    rules: {
      response: [{
        name: 'Security Headers',
        active: true,
        criteria: [{
          variable: 'uri',
          conditional: 'if',
          operator: 'starts_with',
          argument: '/'
        }],
        behavior: {
          addResponseHeader: [
            'X-Frame-Options: SAMEORIGIN',
            'X-Content-Type-Options: nosniff'
          ]
        }
      }]
    }
  }]
};

export default config;
`} />

#### Reference documentation

* [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/)
* [azion.config.js reference](https://www.azion.com/en/documentation/devtools/cli/configs/azion-config-js/)
* [Applications main settings](https://www.azion.com/en/documentation/products/build/applications/main-settings/)

### 6. Migrating Workers to Functions

Functions are the computational engine of modern distributed applications. They often contain the most business-critical logic: authentication, personalization, API orchestration, and integrations with third-party systems.

#### Key Differences

| Aspect | Cloudflare Workers | Azion Functions |
| :----- | :----------------- | :-------------- |
| **Function signature** | `fetch(request, env, ctx)` | `fetch(request, env, ctx)` |
| **Environment access** | `env.VARIABLE` | `Azion.env.get('VARIABLE')` |
| **Memory** | 128 MB (all plans) | 512 MB (all plans) |
| **Cold starts** | Possible | Possible (minimized with node distribution) |

#### Update Function Signature

<Code lang="javascript" code={`
// Before: Cloudflare
export default {
  async fetch(request, env, ctx) {
    const apiKey = env.API_KEY;
    return fetch(apiUrl, { headers: { 'Authorization': \`Bearer \${apiKey}\` }});
  }
};

// After: Azion
export default {
  async fetch(request, env, ctx) {
    const apiKey = Azion.env.get('API_KEY');
    return fetch(apiUrl, { headers: { 'Authorization': \`Bearer \${apiKey}\` }});
  }
};
`} />

#### Update Geo Metadata

<Code lang="javascript" code={`
// Before: Cloudflare
const country = request.cf.country;

// After: Azion
const country = request.metadata['geoip_country_code'];
`} />

#### Update Service Imports

Azion provides two SQL interfaces:
- **Runtime API** (`azion:sql`) — for querying databases from Functions
- **Azion Lib SDK** (`azion/sql`) — for managing databases via API (build tools, scripts)

<Code lang="javascript" code={`
import { Database } from 'azion:sql';

// Open connection (async)
const db = await Database.open('my-database');

// Query and iterate results
const rows = await db.query('SELECT * FROM users');
let row = await rows.next();
while (row) {
  const name = row.getString(0); // access column by index
  console.log(name);
  row = await rows.next();
}
`} />

#### Reference documentation

* [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/)
* [Functions Instances](https://www.azion.com/en/documentation/products/build/applications/functions-instances/)
* [Runtime APIs](https://www.azion.com/en/documentation/products/build/develop-with-azion/runtime-apis/)
* [JavaScript Runtime APIs reference](https://www.azion.com/en/documentation/runtime-apis/javascript/)
* [SQL Database API (Runtime)](https://www.azion.com/en/documentation/runtime/api-reference/sql-database.md)
* [Azion Lib SQL (SDK)](https://www.azion.com/en/documentation/products/azion-lib/sql.md)

### 7. Migrating Load Balancing

Load balancing distributes traffic across multiple origins for high availability and performance. Azion Load Balancer provides health checks, steering policies, and origin failover.

#### Key Differences

| Aspect | Cloudflare Load Balancing | Azion Load Balancer |
| :----- | :------------------------ | :------------------ |
| **Health checks** | HTTP, HTTPS, TCP | HTTP, HTTPS, TCP |
| **Steering policies** | Round-robin, Least connections, Random, Geo | Round-robin, Least connections, Geo |
| **Failover** | Active-passive, Active-active | Active-passive, Active-active |
| **Session affinity** | Cookie, IP hash | Cookie,  IP hash |
| **Origins per pool** | Multiple origins | Multiple origins |

#### Configuration Steps

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Load Balancer**.
3. Create an **Connector** for each origin server.
4. Configure health checks for each origin.
5. Create a **Load Balancer** instance.
6. Add origins to the load balancer pool.
7. Configure steering policy (round-robin, geo, etc.).
8. Set origin weights if using weighted distribution.
9. Enable session affinity if needed.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a Connector (origin) with load balancing configured at the address level
curl -X POST 'https://api.azionapi.net/v4/workspace/connectors' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Origin-US-East",
    "type": "http",
    "attributes": {
      "addresses": [
        {
          "address": "origin1.example.com",
          "active": true,
          "modules": {
            "load_balancer": {
              "weight": 3
            }
          }
        },
        {
          "address": "origin2.example.com",
          "active": true,
          "modules": {
            "load_balancer": {
              "weight": 1
            }
          }
        }
      ]
    }
  }'
`} />
:::note
Load balancing in Azion is configured as a module within Connector addresses, not as a separate resource. The `load_balancer` module supports `weight`, `method` ("round_robin", "least_conn", "ip_hash"), `max_retries`, `connection_timeout`, and `read_write_timeout` settings.
:::
</Fragment>
</Tabs>

#### Load Balancer Module Configuration

<Code lang="javascript" code={`
// Load balancer settings within address modules
{
  "weight": 3,                    // Relative weight for weighted distribution
  "method": "round_robin",        // Options: "round_robin", "least_conn", "ip_hash"
  "max_retries": 3,               // Maximum retry attempts
  "connection_timeout": 10,       // Connection timeout in seconds
  "read_write_timeout": 30        // Read/write timeout in seconds
}
`} />

#### Reference documentation

* [Load Balancer](https://www.azion.com/en/documentation/products/secure/connectors/load-balancer/)
* [Connectors](https://www.azion.com/en/documentation/products/secure/connectors/)

### 8. Migrating Cache Configuration

Caching configuration determines how content is stored and served from distributed locations. Azion Cache provides fine-grained control over cache behavior with Tiered Cache support.

#### Key Differences

| Aspect | Cloudflare Cache | Azion Cache |
| :----- | :--------------- | :---------- |
| **Cache levels** | Regional Tiered Cache + Smart Tiered Cache + Edge + Browser | Cache + Tiered Cache + Browser |
| **Cache key** | Customizable | Customizable via Rules Engine |
| **Purge** | URL, Tag, Host, Prefix | URL, Cache Key, Wildcard |
| **Stale content** | Stale-while-revalidate | Stale-while-revalidate |
| **TTL limits** | Per-page rules | Per-rule configuration |

#### Cache Settings Migration

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Edit your **Application**.
3. Navigate to **Cache Settings**.
4. Configure default cache TTL.
5. Enable **Tiered Cache** for improved hit ratio.
6. Add custom cache rules via **Rules Engine**.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Update cache settings for a specific cache setting within an application
curl -X PATCH 'https://api.azion.com/v4/workspace/applications/{application_id}/cache_settings/{cache_setting_id}' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "my-cache-setting",
    "browser_cache": {
      "ttl": 3600
    },
    "modules": {
      "cache": {
        "ttl": 86400
      },
      "tiered_cache": {
        "enabled": true
      }
    }
  }'
`} />
:::note
Cache settings are managed as sub-resources under applications. You must specify both the `application_id` and the `cache_setting_id` to update cache configuration.
:::
</Fragment>
</Tabs>

#### Tiered Cache

Enable Tiered Cache to improve cache hit ratio:

<Code lang="javascript" code={`
// Tiered cache is configured within cache settings modules
{
  "name": "my-cache-setting",
  "modules": {
    "tiered_cache": {
      "enabled": true
    }
  }
}
`} />

#### Cache Key Customization

Cache key customization uses **Advanced Cache Key** in Cache Settings combined with **Adaptive Delivery** for device-based variations:

**Example: Vary cache by device group**

1. In **Cache Settings**, enable **Adaptive Delivery**
2. Select "Content varies by some Device Groups (Whitelist)"
3. Choose device groups (e.g., Mobile, Desktop)
4. Apply via Rules Engine:

<Code lang="text" code={`
Criteria: \${uri} starts with /images/
Behavior: Set Cache Policy → [cache-setting-name]
`} />

#### Cache Purge

<Code lang="bash" code={`
# Purge by URL
curl -X POST 'https://api.azion.com/v4/workspace/purge/url' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "items": [
      "https://example.com/image.jpg",
      "https://example.com/styles.css"
    ],
    "layer": "cache"
  }'

# Purge by wildcard
curl -X POST 'https://api.azion.com/v4/workspace/purge/wildcard' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "items": ["https://example.com/images/*"],
    "layer": "cache"
  }'
`} />
:::note
Purge is a separate top-level API, not nested under applications. The `layer` parameter is optional with values `cache` (default) or `tiered_cache`.
:::

#### Reference documentation

* [Cache](https://www.azion.com/en/documentation/products/build/applications/cache/)
* [Cache Settings](https://www.azion.com/en/documentation/products/build/applications/cache-settings/)
* [Tiered Cache](https://www.azion.com/en/documentation/products/build/applications/cache/tiered-cache/)
* [Real-Time Purge](https://www.azion.com/en/documentation/products/build/applications/real-time-purge/)
* [Application Accelerator](https://www.azion.com/en/documentation/products/build/applications/application-accelerator/)

### 9. Migrating Image Optimization

Image optimization reduces image file sizes while maintaining visual quality. Azion Image Processor transforms, optimizes, and delivers images from distributed node locations.

#### Key Differences

| Aspect | Cloudflare Images | Azion Image Processor |
| :----- | :---------------- | :-------------------- |
| **Storage** | Built-in storage | Object Storage integration |
| **Transformations** | Resize, format, quality | Resize, format, quality, crop, rotate |
| **URL format** | `/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>` | `/image.png?ims=<OPTIONS>` |
| **Format support** | WebP, AVIF | WebP, AVIF, JPEG, PNG |
| **Signed URLs** | Supported | Supported via Secure Token |

#### Configuration Steps

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Edit your **Application**.
3. Navigate to **Image Processor** settings.
4. Enable Image Processor.
5. Configure default quality and format settings.
6. Set up Object Storage as image source (optional).
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Enable Image Processor within application modules
curl -X PATCH 'https://api.azionapi.net/v4/workspace/applications/{application_id}' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "modules": {
      "image_processor": {
        "enabled": true
      }
    }
  }'
`} />
:::note
The `image_processor` configuration must be nested under `modules` in the request body. Image Processor settings are managed at the application level.
:::
</Fragment>
</Tabs>

#### URL Format

Transform images via query string parameters:

<Code lang="text" code={`
# Cloudflare format
https://example.com/cdn-cgi/image/width=400,quality=85/image.jpg

# Azion format
https://example.com/image.jpg?ims=400x400
`} />

#### Transformation Parameters

Azion Image Processor uses the `ims` query parameter for transformations:

| Syntax | Description | Example |
| :----- | :---------- | :------ |
| `?ims=WxH` | Resize to width x height | `?ims=400x300` |
| `?ims=Wx` | Resize to width (auto height) | `?ims=400x` |
| `?ims=xH` | Resize to height (auto width) | `?ims=x300` |
| `?ims=WxH:fill` | Crop to exact dimensions | `?ims=400x300:fill` |
| `?ims=WxH:fit` | Fit within dimensions | `?ims=400x300:fit` |

:::note
Azion Image Processor automatically optimizes image format based on the client's `Accept` header, serving WebP or AVIF to supported browsers.
:::

#### Reference documentation

* [Image Processor](https://www.azion.com/en/documentation/products/build/applications/image-processor/)
* [How to process images](https://www.azion.com/en/documentation/products/guides/build/process-images/)
* [Object Storage](https://www.azion.com/en/documentation/products/store/object-storage/)

### 10. Migrating AI Workloads (Workers AI to AI Inference)

AI inference enables low-latency AI-powered features in applications. Azion AI Inference provides GPU-backed inference for text and visual models, allowing you to run AI workloads close to your users.

#### Key Differences

| Aspect | Cloudflare Workers AI | Azion AI Inference |
| :----- | :-------------------- | :----------------- |
| **Model hosting** | Cloudflare-hosted models | Custom model deployment |
| **Inference API** | REST API | REST API + Functions |
| **Model types** | Text generation, image, speech | Custom models, LLMs |
| **GPU support** | Shared GPU | Dedicated GPU instances |

#### Using AI Inference

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **AI Inference** (via Marketplace or Functions).
3. Deploy a model or use pre-built templates.
4. Configure inference endpoint.
5. Integrate with your application via Functions.
</Fragment>

<Fragment slot="panel.api">
<Code lang="javascript" code={`
// AI inference in Functions
export default {
  async fetch(request) {
    const response = await fetch('https://ai-inference.example.com/v1/predict', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': \`Bearer \${Azion.env.get('AI_API_KEY')}\`
      },
      body: JSON.stringify({
        model: 'text-generation',
        prompt: await request.text()
      })
    });
    return response;
  }
};
`} />
</Fragment>
</Tabs>

#### AI Starter Kit

Use the AI Inference Starter Kit template:

<Code lang="bash" code={`
# Deploy via CLI
azion deploy --template ai-inference-starter-kit
`} />

#### Reference documentation

* [AI Inference](https://www.azion.com/en/documentation/products/ai/ai-inference/)
* [AI Inference models](https://www.azion.com/en/documentation/products/ai/ai-inference/models/)
* [AI Inference Starter Kit](https://www.azion.com/en/documentation/products/guides/ai-inference-starter-kit/)

## Secure

The Secure category covers domains, DNS, certificates, firewall rules, and protection against malicious traffic. Plan these migrations as controlled cutovers, since they affect how users reach your application and how it is protected in production.

### 1. Migrating Custom Domains

Custom domain migration is one of the most sensitive parts of any platform transition. It affects users, SEO, brand trust, and production availability. Plan domain migration as a controlled cutover, not a last-minute DNS change.

#### Migration Strategies

| Strategy | Best For | DNS Control |
| :------- | :------- | :---------- |
| **CNAME** | Quick subdomain migration | Keep your DNS provider |
| **Nameserver** | Full DNS control and apex domains | Transfer DNS to Azion |

#### Create the Certificate

Create your SSL/TLS certificate **before** pointing your domain to Azion. This ensures users can access the application securely over HTTPS when the domain starts resolving to the new infrastructure.

Azion provides free Let's Encrypt certificates with automatic renewal.

#### Configure the Domain

Create a workload in Azion Console and associate your custom domain. See [Workloads Documentation](https://www.azion.com/en/documentation/products/secure/workloads/).

#### Point the Domain to Azion

<Tabs client:visible>
    <Fragment slot="tab.cname">CNAME Migration</Fragment>
    <Fragment slot="tab.nameserver">Nameserver Migration</Fragment>

<Fragment slot="panel.cname">
Point the subdomain to the Azion-generated domain:

<Code lang="text" code={`
www CNAME xxxxxxxxxx.map.azionedge.net
`} />

This keeps your current DNS provider while routing traffic through Azion.
</Fragment>

<Fragment slot="panel.nameserver">
Configure your domain to use Azion DNS nameservers:

<Code lang="text" code={`
ns1.aziondns.net
ns2.aziondns.com
ns3.aziondns.org
`} />

This gives Azion full DNS control, required for apex domains.
</Fragment>
</Tabs>

#### Verify Propagation

<Code lang="bash" code={`
dig www.yourdomain.com CNAME +short
`} />

:::caution[warning]
Before switching production traffic, confirm: certificate is active, domain is associated with correct workload, DNS records are ready, critical routes have been tested, redirects behave as expected, and monitoring is configured for post-cutover validation.
:::

#### Reference documentation

* [Workloads](https://www.azion.com/en/documentation/products/secure/workloads/)
* [Create an Azion custom domain](https://www.azion.com/en/documentation/products/guides/create-azion-custom-domain/)
* [Edge DNS](https://www.azion.com/en/documentation/products/secure/edge-dns/)
* [Certificate Manager](https://www.azion.com/en/documentation/products/secure/firewall/certificate-manager/)

### 2. Migrating DNS to Edge DNS

DNS configuration is foundational to application delivery. Migrating DNS requires careful planning to avoid downtime during the nameserver switch.

#### Key Differences

| Aspect | Cloudflare DNS | Azion Edge DNS |
| :----- | :------------- | :------------- |
| **Nameservers** | Assigned per zone | `ns1.aziondns.net`, `ns2.aziondns.com`, `ns3.aziondns.org` |
| **Record types** | A, AAAA, CNAME, MX, TXT, SRV, NS, etc. | A, AAAA, CNAME, MX, TXT, SRV, NS, CAA, PTR |
| **DNSSEC** | Supported | Supported |
| **API** | REST API | REST API v4 |
| **Anycast** | Global Anycast | Global Anycast |

#### Migration Steps

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Edge DNS**.
3. Click **+ Zone** to create a new DNS zone.
4. Enter your domain name.
5. Add DNS records matching your Cloudflare configuration.
6. Note the Azion nameservers assigned to your zone.
7. Update nameservers at your domain registrar.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a DNS zone
curl -X POST 'https://api.azionapi.net/v4/workspace/dns/zones' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "my-zone",
    "domain": "example.com",
    "active": true
  }'

# Add DNS records
curl -X POST 'https://api.azionapi.net/v4/workspace/dns/zones/{zone_id}/records' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "record_type": "A",
    "entry": "www",
    "ttl": 3600,
    "rdata": ["192.168.1.1"]
  }'
`} />
:::note
DNS zones require `name`, `domain`, and `active` fields. DNS records use `rdata` as an array of strings (e.g., `["192.168.1.1"]` for A records, `["mail.example.com"]` for CNAME). The `entry` field specifies the record name prefix.
:::
</Fragment>
</Tabs>

#### Record Type Mapping

| Cloudflare Record | Azion Edge DNS | Notes |
| :---------------- | :------------- | :---- |
| A | A | Direct IP mapping |
| AAAA | AAAA | IPv6 address |
| CNAME | CNAME | Alias to another domain |
| MX | MX | Mail exchange (include priority) |
| TXT | TXT | Text records (SPF, DKIM) |
| SRV | SRV | Service records |
| CAA | CAA | Certificate Authority Authorization |
| NS | NS | Nameserver delegation |

#### DNSSEC Configuration

To enable DNSSEC:

1. Navigate to your zone in Edge DNS.
2. Go to **DNSSEC** tab.
3. Enable DNSSEC.
4. Copy the DS record to your registrar.

<Code lang="bash" code={`
# Verify DNSSEC
dig example.com DNSSEC +dnssec
`} />

#### Verify Propagation

<Code lang="bash" code={`
# Check nameserver propagation
dig example.com NS +short

# Check specific record
dig www.example.com A +short

# Check from specific DNS server
dig @ns1.aziondns.net example.com A
`} />

#### Reference documentation

* [Edge DNS](https://www.azion.com/en/documentation/products/secure/edge-dns/)
* [DNSSEC compatibility](https://www.azion.com/en/documentation/products/secure/edge-dns/dnssec-compatibility/)
* [Run the dig command](https://www.azion.com/en/documentation/products/guides/run-the-dig-command/)
* [Run the traceroute command](https://www.azion.com/en/documentation/products/guides/run-the-traceroute-command/)

### 3. Migrating SSL/TLS to Certificate Manager

SSL/TLS certificates ensure secure communication between clients and your application. Azion provides automatic certificate provisioning and supports custom certificates.

#### Key Differences

| Area                              | Cloudflare SSL/TLS                                                                                                                                    | Azion Certificate Manager                                                                                                                                                                                 |
| :-------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Product scope**                 | Broader SSL/TLS suite covering edge certificates, origin certificates, encryption modes, mTLS, custom TLS settings, and related controls.             | Focused on managing TLS certificates and associating them with Azion Domains or Workloads.                                                                                                                |
| **Main certificate options**      | Universal SSL, Advanced certificates, and Custom certificates.                                                                                        | Azion SAN, Custom certificate, Let’s Encrypt certificate, and Trusted CA for mTLS.                                                                                                                        |
| **Default managed certificate**   | Universal SSL automatically covers the apex domain and first-level subdomains.                                                                        | Let’s Encrypt is the main managed option for customer-owned custom domains. Azion SAN applies to Azion-provided `azionedge.net` addresses.                                                                |
| **Advanced managed certificates** | Advanced certificates allow more control, such as CA, hostnames, and validity period.                                                                 | Azion does not position an equivalent “Advanced Certificate Manager” layer in the same way; use Let’s Encrypt for managed DV or Custom certificate for full control.                                      |
| **Custom certificates**           | Supported for customers who want their own certificate, CA control, OV, or EV. Customer handles issuance and renewal.                                 | Supported by uploading a TLS certificate and private key. Azion accepts single-domain or SAN certificates.                                                                                                |
| **Validation**                    | Cloudflare uses Domain Control Validation; with Cloudflare DNS it can happen automatically, while external DNS may require manual DCV.                | Let’s Encrypt validation supports DNS-01 and HTTP-01 challenges.                                                                                                                                          |
| **Renewal**                       | Universal SSL and Advanced certificates are managed by Cloudflare; uploaded Custom certificates are not renewed by Cloudflare.                        | Let’s Encrypt certificates are automatically renewed by Azion before expiration; custom certificates depend on the customer lifecycle.                                                                    |
| **Origin encryption model**       | Cloudflare explicitly manages the visitor-to-Cloudflare and Cloudflare-to-origin model through SSL/TLS encryption modes such as Full and Full Strict. | Azion Certificate Manager focuses on certificates for HTTPS traffic on Azion; origin/TLS behavior is configured through the broader application/workload setup, not as a Cloudflare-style SSL mode model. |
| **Origin CA**                     | Cloudflare has Origin CA certificates for encrypting traffic between Cloudflare and the origin when traffic is proxied through Cloudflare.            | No direct equivalent should be described as “Origin CA”; use custom certificates or origin/application configuration depending on the architecture.                                                       |
| **mTLS**                          | Cloudflare supports client certificates and BYOCA for mTLS, plus Authenticated Origin Pulls for Cloudflare-to-origin authentication.                  | Azion supports mTLS through Trusted CA certificates; Azion SAN certificates do not support mTLS.                                                                                                          |


#### Automatic Certificate Provisioning

Azion automatically provisions Let's Encrypt certificates for custom domains:

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Create or edit a **Workload**.
3. Add your custom domain.
4. Azion automatically provisions a Let's Encrypt certificate.
5. Verify domain ownership (if required).
6. Wait for certificate activation (typically 5-15 minutes).
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a workload with TLS configuration
# First, create a certificate via Certificate Manager, then reference it by ID
curl -X POST 'https://api.azionapi.net/v4/workspace/workloads' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "my-workload",
    "domains": ["www.example.com"],
    "tls": {
      "certificate": 12345,
      "minimum_version": "tls12",
      "ciphers": 1
    },
    "active": true,
    "infrastructure": 1
  }'
`} />
:::note
The `tls.certificate` field references an existing certificate ID from Certificate Manager. Use the Console to provision Let's Encrypt certificates automatically, or upload custom certificates via the Certificate Manager API.
:::
</Fragment>
</Tabs>

#### Custom Certificate Upload

For organizations with existing certificates:

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Go to **Products menu** > **Certificate Manager**.
2. Click **+ Certificate**.
3. Select **Custom Certificate**.
4. Upload your certificate (PEM format).
5. Upload your private key.
6. Upload intermediate CA chain (if applicable).
7. Associate the certificate with your workload.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Upload custom certificate
curl -X POST 'https://api.azionapi.net/v4/workspace/tls/certificates' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "my-custom-cert",
    "certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
  }'
`} />
:::note
The certificates endpoint is `/v4/workspace/tls/certificates`. The certificate and private key should be in PEM format. Intermediate CA certificates can be appended to the certificate field if needed.
:::
</Fragment>
</Tabs>

#### mTLS Configuration

For mutual TLS authentication:

1. Navigate to **Certificate Manager**.
2. Upload your CA certificate as a Trusted CA.
3. Configure your workload to require client certificates.
4. See the [mTLS configuration guide](/en/documentation/products/guides/mtls/) for detailed steps.

#### Reference documentation

* [Certificate Manager](https://www.azion.com/en/documentation/products/secure/firewall/certificate-manager/)
* [Create a digital certificate](https://www.azion.com/en/documentation/products/guides/create-a-digital-certificate/)
* [mTLS](https://www.azion.com/en/documentation/products/secure/firewall/mtls/)

### 4. Migrating WAF to Web Application Firewall

Web Application Firewall protects applications from malicious traffic, SQL injection, cross-site scripting (XSS), and other application-layer attacks. Migrating WAF rules requires careful mapping of rule logic and understanding differences in rule construction.

#### Key Differences

| Aspect | Cloudflare WAF | Azion WAF |
| :----- | :------------- | :-------- |
| **Rule language** | Expression language | Rules Engine criteria |
| **Managed rulesets** | Cloudflare-managed rules | Azion-managed rulesets |
| **Custom rules** | Firewall Rules | Rules Engine for Firewall |
| **OWASP coverage** | OWASP Core Rule Set | OWASP Top 10 coverage |
| **Mode options** | Block, Challenge, Log | Learning, Blocking |

#### Migration Steps

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Firewall**.
3. Select or create a Firewall instance.
4. Navigate to **WAF** tab.
5. Enable desired managed rulesets (SQL Injection, XSS, etc.).
6. Configure sensitivity level per ruleset.
7. Create custom rules in **Rules Engine** tab.
8. Associate the Firewall with your application.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a WAF instance
curl -X POST 'https://api.azion.com/v4/workspace/wafs' \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN]' \
  --header 'Content-Type: application/json' \
  --data '{
    "active": true,
    "name": "My WAF",
    "product_version": "1.0",
    "engine_settings": {
      "engine_version": "2021-Q3",
      "type": "score",
      "attributes": {
        "rulesets": [1],
        "thresholds": [
          { "threat": "sql_injection", "sensitivity": "medium" }
        ]
      }
    }
  }'
`} />
:::note
WAF instances are created via the `/v4/workspace/wafs` endpoint. The `engine_settings` configuration defines threat detection rulesets and sensitivity thresholds. For custom WAF rules, use the Firewall Rules Engine.
:::
</Fragment>
</Tabs>

#### Rule Migration Example

Convert Cloudflare firewall rule to Azion Rules Engine:

**Cloudflare expression:**
<Code lang="text" code={`
(http.request.uri.path contains "/admin" and not ip.src in {10.0.0.0/8})
`} />

**Azion criteria:**
<Code lang="text" code={`
Variable: \${uri}
Operator: matches
Argument: /admin

AND

Variable: \${remote_addr}
Operator: does not match
Argument: 10.0.0.0/8
`} />

:::note
Azion WAF operates in Learning mode by default, analyzing traffic patterns before active blocking. Use this mode to validate rule behavior before switching to Blocking mode.
:::

#### Reference documentation

* [Web Application Firewall](https://www.azion.com/en/documentation/products/secure/firewall/web-application-firewall/)
* [Rules Engine for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/rules-engine/)
* [Functions for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/functions/)

### 5. Migrating DDoS Protection

DDoS protection guards against volumetric attacks, protocol attacks, and application layer attacks. Azion provides automatic DDoS mitigation with no configuration required for most attack types.

#### Key Differences

| Aspect | Cloudflare DDoS | Azion DDoS Protection |
| :----- | :-------------- | :-------------------- |
| **Activation** | Automatic | Automatic |
| **Layer coverage** | L3, L4, L7 | L3, L4, L7 |
| **Billing** | Unmetered (standard) | Unmetered |
| **Customization** | Managed rules + custom | Managed rules + Rules Engine |

#### Automatic Protection

Azion DDoS Protection activates automatically for all applications. No manual configuration is required for standard protection against:

* Volumetric attacks (UDP floods, ICMP floods)
* Protocol attacks (SYN floods, packet fragmentation)
* Application layer attacks (HTTP floods, slowloris)

#### Advanced Configuration

For applications requiring specific DDoS policies:

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Firewall**.
3. Select your Firewall instance.
4. Navigate to **DDoS Protection** tab.
5. Configure threshold settings.
6. Enable/disable specific mitigation rules.
7. Set up alert notifications.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# DDoS protection is configured as a module within Firewall
# Update the Firewall with DDoS module settings
curl -X PATCH 'https://api.azion.com/v4/workspace/firewalls/{firewall_id}' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "modules": {
      "ddos_protection": {
        "enabled": true,
        "sensitivity": "high"
      }
    }
  }'
`} />
:::note
DDoS protection is a module configured within the Firewall resource, not a separate endpoint. Configure it through the `modules.ddos_protection` field when creating or updating a Firewall instance.
:::
</Fragment>
</Tabs>

#### Network Shield

For network-layer protection, use Azion Network Shield:

* Provides L3/L4 DDoS protection
* Works with Edge DNS for traffic filtering
* Integrates with Firewall for unified security

#### Reference documentation

* [DDoS Protection](https://www.azion.com/en/documentation/products/secure/firewall/ddos-protection/)
* [DDoS Mitigation](https://www.azion.com/en/documentation/products/secure/firewall/ddos-protection/ddos-mitigation/)
* [Network Shield](https://www.azion.com/en/documentation/products/secure/firewall/network-shield/)

### 6. Migrating Bot Management

Bot management protects applications from automated threats while allowing legitimate bots. Azion Bot Manager provides detection, challenge, and mitigation capabilities.

#### Key Differences

| Aspect | Cloudflare Bots | Azion Bot Manager |
| :----- | :-------------- | :---------------- |
| **Detection** | Machine learning, heuristics, fingerprinting, JavaScript Detections | Machine learning, behavioral analysis, fingerprinting, Reputation Intelligence |
| **Challenge** | JavaScript Detections, Managed Challenge, Turnstile | JavaScript injection (fingerprinting), ALTCHA (via redirect) |
| **Actions** | Allow, Managed Challenge, Block | Allow, Deny, Drop, Redirect, Custom HTML, Random Delay, Hold Connection |
| **Lite version** | Bot Fight Mode | Bot Manager Lite (Marketplace) |

#### Bot Manager Lite (Marketplace)

For basic bot protection, install Bot Manager Lite from Azion Marketplace:

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.marketplace">Marketplace</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Marketplace**.
3. Search for **Bot Manager Lite**.
4. Click **Install**.
5. Configure detection sensitivity.
6. Set up response actions (challenge, block).
7. Associate with your Firewall instance.
</Fragment>

<Fragment slot="panel.marketplace">
Bot Manager Lite provides:
* Score-based bot detection with configurable threshold
* Multiple response actions (deny, drop, redirect, custom HTML)
* IP reputation validation via network lists
* Adjustable tolerance levels (soft, medium, hard)
</Fragment>
</Tabs>

#### Custom Bot Rules

Create custom rules to handle specific bots:

<Code lang="text" code={`
Criteria: \${user_agent} contains "BadBot"
Behavior: Deny (403)

Criteria: \${user_agent} contains "Googlebot"
Behavior: Allow
`} />

#### Verification

<Code lang="bash" code={`
# Test bot detection
curl -A "BadBot/1.0" https://yourdomain.com/
# Expected: 403 Forbidden or challenge page

curl -A "Mozilla/5.0" https://yourdomain.com/
# Expected: Normal response
`} />

#### Reference documentation

* [Bot Manager](https://www.azion.com/en/documentation/products/secure/firewall/bot-manager/)
* [Bot Manager Lite](https://www.azion.com/en/documentation/products/secure/firewall/bot-manager-lite/)
* [Bot Manager Lite integration kit](https://www.azion.com/en/documentation/products/guides/bot-manager-lite-integration-kit/)
* [Radware Bot Manager](https://www.azion.com/en/documentation/products/guides/radware-bot-manager/)

### 7. Migrating Rate Limiting

Rate limiting protects applications from abuse by limiting request rates per client. Azion provides rate limiting through Firewall rules and Functions.

#### Key Differences

| Aspect | Cloudflare Rate Limiting | Azion Rate Limiting |
| :----- | :----------------------- | :----------------- |
| **Configuration** | Dedicated rate limiting rules | Firewall rules + Functions |
| **Granularity** | Path, method, country | Path, method, IP, custom |
| **Actions** | Block, Challenge, Log | Block, Log |
| **Window** | 10 seconds to 1 hour | Customizable |

#### Firewall-Based Rate Limiting

Configure rate limiting in Firewall Rules Engine:

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Firewall** > **Rules Engine**.
3. Create a new rule.
4. Set criteria (path, method, etc.).
5. Add **Rate Limit** behavior.
6. Configure requests per second/minute.
7. Set action (Block, Log).
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create rate limiting rule
curl -X POST 'https://api.azionapi.net/v4/workspace/firewalls/{firewall_id}/request_rules' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Rate Limit API",
    "criteria": [[{"variable": "\${uri}", "operator": "starts_with", "argument": "/api/"}]],
    "behaviors": [
      {"type": "rate_limit", "attributes": {"rps": 100, "window": 60, "action": "block"}}
    ]
  }'
`} />
:::note
Firewall rules are created under `/v4/workspace/firewalls/{firewall_id}/request_rules`. The path follows the workspace resource pattern.
:::
</Fragment>
</Tabs>


#### Reference documentation

* [Rules Engine for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/rules-engine/)
* [Functions for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/functions/)
* [Functions Instances for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/functions-instances/)

## Store

The Store category covers data services. Migrate key-value, object, and SQL data with attention to consistency, access patterns, and application compatibility.

### 1. Migrating Workers KV with KV Store

Key-value storage is used for fast access to configuration, user preferences, session metadata, feature flags, and personalization data. The migration should preserve data consistency and application compatibility.

#### API Comparison

<Code lang="javascript" code={`
// Before: Cloudflare
await env.MY_KV_NAMESPACE.put('key1', 'value1');
const value = await env.MY_KV_NAMESPACE.get('key1');

// After: Azion
import { KVStore } from 'azion:kv';

const kv = new KVStore('my-store');
await kv.put('key1', 'value1');
const value = await kv.get('key1');
`} />

#### Export and Import

Export existing KV data through Cloudflare's API. Before importing, review:

* Key naming conventions and prefixes
* Expiration logic
* Value formats and serialized object structure
* Missing-key and default value behavior

#### Reference documentation

* [KV Store (azion:kv module)](https://www.azion.com/en/documentation/products/azion-lib/kv/)
* [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/)
* [Runtime APIs](https://www.azion.com/en/documentation/products/build/develop-with-azion/runtime-apis/)

### 2. Migrating R2 with Object Storage

Object storage powers files that matter to users and business operations: images, documents, static assets, media files, uploads, and generated content.

#### Key Differences

| Aspect | Cloudflare R2 | Azion Object Storage |
| :----- | :------------ | :------------------- |
| **Endpoint** | `<ACCOUNT_ID>.r2.cloudflarestorage.com` | `s3.us-east-005.azionstorage.net` |
| **Region** | `auto` | `us-east-005` |
| **Data transfer out** | Free | Zero cost |

#### Update Configuration

<Code lang="javascript" code={`
import { S3Client } from '@aws-sdk/client-s3';

const client = new S3Client({
  region: 'us-east-005',
  endpoint: 'https://s3.us-east-005.azionstorage.net',
  credentials: {
    accessKeyId: Azion.env.get('AZION_ACCESS_KEY'),
    secretAccessKey: Azion.env.get('AZION_SECRET_KEY')
  }
});
`} />

#### Migrate Data with s3cmd

[s3cmd](https://s3tools.org/s3cmd) is a command-line tool for managing S3-compatible storage services. It's an effective option for migrating data from Cloudflare R2 to Azion Object Storage.

1. Install `s3cmd` and run `s3cmd --configure` to set up your Azion credentials:

* **Access Key / Secret Key:** Enter the keys generated for Azion Object Storage.
* **Default Region:** `us-east-005` (s3cmd also accepts `us-east` for interactive configuration).
* **S3 Endpoint:** `s3.us-east-005.azionstorage.net`.
* **DNS template:** `%(bucket).s3.us-east-005.azionstorage.net`.
* **Use HTTPS protocol:** `true`.

2. Use the following commands to migrate your data:

| Command | Description |
| :------ | :---------- |
| `s3cmd ls` | Lists all buckets. |
| `s3cmd put file.png s3://my-bucket/` | Uploads an object. |
| `s3cmd get s3://my-bucket/file.png` | Downloads an object. |
| `s3cmd sync s3://source-bucket/ s3://dest-bucket/` | Syncs between buckets. |

:::note
Migrate data using familiar tools such as s3cmd, rclone, or AWS CLI. Before migration, map buckets, object prefixes, public/private assets, access patterns, and signed URL logic.
:::

#### Reference documentation

* [Object Storage](https://www.azion.com/en/documentation/products/store/object-storage/)
* [Use S3-compatible tools with Object Storage](https://www.azion.com/en/documentation/products/guides/use-s3-compatible-tools-with-object-storage/)
* [Create and modify a bucket](https://www.azion.com/en/documentation/products/guides/create-and-modify-bucket/)
* [Upload and download objects](https://www.azion.com/en/documentation/products/guides/upload-and-download-objects-from-bucket/)
* [Use a bucket as origin](https://www.azion.com/en/documentation/products/store/storage/use-bucket-as-origin/)
* [Storage library reference](https://www.azion.com/en/documentation/products/azion-lib/storage/)

### 3. Migrating D1 with SQL Database

Database migration touches the core of application state. Azion SQL Database is SQLite-compatible, ACID-compliant, and uses a distributed Main/Replicas architecture.

#### Key Differences

| Aspect | Cloudflare D1 | Azion SQL Database |
| :----- | :------------ | :----------------- |
| **Connection** | `env.DB` binding | `new Database('name')` |
| **SQL dialect** | SQLite | SQLite |
| **Vector search** | Supported | Supported |

#### Update Your Code

<Code lang="javascript" code={`
// Before: Cloudflare
const result = await env.DB
  .prepare('SELECT * FROM users WHERE id = ?')
  .bind(1)
  .first();

// After: Azion
import { Database } from 'azion:sql';

const db = new Database('my-database');
const result = await db
  .prepare('SELECT * FROM users WHERE id = ?')
  .bind(1)
  .first();
`} />

#### Export and Import

<Code lang="bash" code={`
# Export from D1
wrangler d1 export my-db --output=dump.sql

# Import to Azion (via SQL Shell CLI or migration workflow)
`} />

#### Reference documentation

* [SQL Database](https://www.azion.com/en/documentation/products/store/sql-database/)
* [Vector Search](https://www.azion.com/en/documentation/products/store/sql-database/vector-search/)
* [Create a database](https://www.azion.com/en/documentation/products/store/sql/create-database/)
* [Install SQL Shell](https://www.azion.com/en/documentation/products/store/sql/install-edge-sql-shell/)
* [SQL Database Shell commands](https://www.azion.com/en/documentation/products/store/sql/sql-database-shell-commands/)
* [Import data into SQL Database](https://www.azion.com/en/documentation/products/guides/import-data-sql-database/)

## Observe

The Observe category covers analytics, metrics, and logs. Migrating observability ensures you keep production visibility, troubleshooting capabilities, and compliance reporting after the cutover.

### 1. Migrating Analytics to Real-Time Metrics

Analytics provide visibility into application performance, traffic patterns, and user behavior. Azion offers comprehensive observability through Real-Time Metrics, Real-Time Events, and GraphQL API.

#### Key Differences

| Aspect | Cloudflare Analytics | Azion Real-Time Metrics |
| :----- | :------------------- | :---------------------- |
| **Data freshness** | Near real-time | Near real-time (up to 10 minutes) |
| **Retention** | 30 days (free), 1 year (paid) | 2 years |
| **Query method** | Dashboard, API | Dashboard, GraphQL API |
| **Metrics** | Requests, bandwidth, errors | Requests, bandwidth, errors, latency, cache |
| **Granularity** | Per-minute aggregates | Adaptive intervals (minute/hour/day) |

#### Available Metrics

Azion Real-Time Metrics tracks:

* **Request metrics**: Total requests, requests by status code, requests by HTTP method
* **Performance metrics**: Response time, upstream header time (equivalent to TTFB), origin response time
* **Bandwidth metrics**: Data transferred, data saved by cache
* **Cache metrics**: Hit ratio, miss ratio, expired objects
* **Error metrics**: 4xx errors, 5xx errors, origin errors

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API (GraphQL)</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Real-Time Metrics**.
3. Select your application or workload.
4. Configure time range and filters.
5. Export data if needed.
</Fragment>

<Fragment slot="panel.api">
<Code lang="graphql" code={`
query HttpMetricsQuery {
  httpMetrics(
    limit: 10,
    filter: {
      tsRange: {begin: "2024-01-01T00:00:00", end: "2024-01-02T00:00:00"}
    }
    aggregate: {sum: requests}
    groupBy: [ts]
  ) {
    ts
    sum
  }
}
`} />
</Fragment>
</Tabs>

#### Reference documentation

* [Real-Time Metrics](https://www.azion.com/en/documentation/products/observe/real-time-metrics/)
* [Real-Time Metrics first steps](https://www.azion.com/en/documentation/products/observe/real-time-metrics/first-steps/)
* [Historical Real-Time Metrics](https://www.azion.com/en/documentation/products/observe/historical-real-time-metrics/)
* [Analyze metrics](https://www.azion.com/en/documentation/products/guides/observe/analyze-metrics/)
* [Grafana plugin custom dashboards](https://www.azion.com/en/documentation/products/guides/azion-plugin-grafana-custom-dash/)
* [Grafana plugin pre-built dashboards](https://www.azion.com/en/documentation/products/guides/azion-plugin-grafana-pre-built-dash/)
* [Edge Pulse](https://www.azion.com/en/documentation/products/observe/edge-pulse/)

### 2. Migrating Logs to Real-Time Events

Log data is essential for debugging, security analysis, and compliance. Real-Time Events provides immediate log access through Console or GraphQL API for real-time troubleshooting and investigation.

#### Key Differences

| Aspect | Cloudflare Logs | Azion Real-Time Events |
| :----- | :-------------- | :--------------------- |
| **Access method** | Pull API, Push to S3 | Real-time query via Console or GraphQL API |
| **Latency** | Minutes | Seconds |
| **Retention** | Configurable | Configurable |
| **Format** | JSON | JSON, customizable |
| **Query interface** | API | Console + GraphQL API |

#### Access Real-Time Events

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API (GraphQL)</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Real-Time Events**.
3. Select the dataset (HTTP Requests, WAF, etc.).
4. Configure time range and filters.
5. Click **Search** to query logs.
6. Click any row to see detailed log information.
</Fragment>

<Fragment slot="panel.api">
<Code lang="graphql" code={`
query HttpEvents {
  workloadEvents(
    limit: 100,
    filter: {
      tsRange: {begin: "2024-01-01T00:00:00", end: "2024-01-01T01:00:00"}
    }
  ) {
    ts
    remoteAddress
    requestUri
    status
    upstreamResponseTime
  }
}
`} />
</Fragment>
</Tabs>

#### Reference documentation

* [Real-Time Events](https://www.azion.com/en/documentation/products/observe/real-time-events/)
* [Real-Time Events first steps](https://www.azion.com/en/documentation/products/observe/real-time-events/first-steps/)
* [Investigate requests with the GraphQL API](https://www.azion.com/en/documentation/products/guides/observe/investigate-requests-graphql-api/)
* [Configure sampling](https://www.azion.com/en/documentation/products/guides/observe/configure-sampling/)

### 3. Migrating Logs to Data Stream

Data Stream exports logs continuously to external destinations for long-term storage, analysis, and integration with external monitoring and security systems.

#### Key Differences

| Aspect | Cloudflare Logs | Azion Data Stream |
| :----- | :-------------- | :---------------- |
| **Access method** | Pull API, Push to S3 | Push to 10+ destinations |
| **Latency** | Minutes | Seconds |
| **Retention** | Configurable | Configurable (via destination) |
| **Format** | JSON | JSON, customizable |
| **Destinations** | S3, Azure, GCS | S3, Azure Blob, Datadog, Splunk, Kafka, BigQuery, and more |

#### Configure Data Stream

<Tabs client:visible>
    <Fragment slot="tab.console">Console</Fragment>
    <Fragment slot="tab.api">API</Fragment>

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Data Stream**.
3. Click **+ Stream**.
4. Configure the source (Applications, WAF, etc.).
5. Select or create a template for log format.
6. Choose destination (S3, Datadog, Splunk, etc.).
7. Configure destination credentials.
8. Activate the stream.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a Data Stream
curl -X POST 'https://api.azion.com/v4/workspace/stream/streams' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "My Log Stream",
    "source": {
      "type": "applications"
    },
    "template_id": 12345,
    "endpoint": {
      "type": "s3",
      "name": "my-s3-endpoint",
      "bucket": "my-logs-bucket",
      "region": "us-east-1",
      "access_key": "YOUR_ACCESS_KEY",
      "secret_key": "YOUR_SECRET_KEY"
    },
    "active": true
  }'
`} />
:::note
Data Stream uses `/v4/workspace/stream/streams` endpoint. The request body structure differs from Cloudflare's format. Use `template_id` for predefined templates or create custom templates separately.
:::
</Fragment>
</Tabs>

#### Supported Destinations

Data Stream supports 10+ destinations:

* **Cloud Storage**: Amazon S3, Azure Blob Storage, Azion Object Storage
* **Monitoring**: Datadog, Splunk, Elasticsearch, Azure Monitor
* **Streaming**: AWS Kinesis Data Firehose, Apache Kafka
* **Analytics**: Google BigQuery
* **Security**: IBM QRadar
* **Custom**: HTTP Webhook, Standard HTTP/HTTPS POST

#### Reference documentation

* [Data Stream](https://www.azion.com/en/documentation/products/observe/data-stream/)
* [Data Stream first steps](https://www.azion.com/en/documentation/products/observe/data-stream/first-steps/)
* [Use Data Stream](https://www.azion.com/en/documentation/products/guides/use-data-stream/)
* Connectors: [Amazon S3](https://www.azion.com/en/documentation/products/guides/endpoint-amazon-s3/), [Azion Object Storage](https://www.azion.com/en/documentation/products/guides/connector-azion-object-storage/), [Datadog](https://www.azion.com/en/documentation/products/guides/endpoint-datadog/), [Splunk](https://www.azion.com/en/documentation/products/guides/endpoint-splunk/), [Elasticsearch](https://www.azion.com/en/documentation/products/guides/endpoint-elasticsearch/), [Kinesis](https://www.azion.com/en/documentation/products/guides/endpoint-amazon-kinesis/), [BigQuery](https://www.azion.com/en/documentation/products/guides/endpoint-google-bigquery/)

## Troubleshooting

### Common Issues

| Issue | Solution |
| :---- | :------- |
| **Build fails on Azion** | Check framework preset matches your project; verify build command in `azion.config.js` |
| **Environment variables not found** | Confirm variables created in Azion Console; check code uses `Azion.env.get()` syntax |
| **Redirects not working** | Verify regex patterns are correct; check Rules Engine criteria syntax |
| **Functions return errors** | Update function signature to `fetch(request)`; verify `Azion.env.get()` for variables |
| **KV data missing** | Re-export from Cloudflare; verify import completed without errors |
| **Object Storage access denied** | Check S3 credentials are correct; verify endpoint is `s3.us-east-005.azionstorage.net` |
| **Database queries fail** | Confirm schema imported correctly; verify `new Database('name')` syntax |
| **DNS not resolving** | Check CNAME or nameserver configuration; allow time for propagation |
| **Certificate not active** | Verify domain ownership; check certificate provisioning status |


## Key Advantages After Migration

Migrating from Cloudflare to Azion is straightforward for most modern applications, especially those using Workers, KV, R2, or D1. The immediate goal of migration is continuity—your application should keep working, users should keep accessing the same experiences, and critical business flows should remain stable.

But the larger value comes after the migration, when the team starts operating on a more unified platform.

| Area                   | Advantage after migration                       | What it means in practice                                                                                               |
| :--------------------- | :---------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| **Migration strategy** | **Incremental migration path**                  | Teams can migrate one layer at a time: application, domains, functions, storage, database, security, and observability. |
| **Platform model**     | **Unified application platform**                | Build, Secure, Store, and Observe capabilities are managed through a more connected platform model.                     |
| **Build**              | **Modern application deployment**               | Applications can be deployed from GitHub or CLI, with framework detection and Azion configuration.                      |
| **Build**              | **Serverless compute with zero cold starts**    | Functions are designed for consistent first-request performance on Azion’s distributed infrastructure.                  |
| **Build**              | **Rules-based application control**             | Rules Engine can manage redirects, rewrites, headers, cache behavior, routing, and request/response logic.              |
| **Build**              | **Integrated cache and acceleration**           | Cache, Tiered Cache, and Application Accelerator can be configured as part of the application delivery layer.           |
| **Build**              | **Image optimization at delivery time**         | Image Processor can transform and optimize images through URL parameters and application configuration.                 |
| **Secure**             | **Controlled domain and DNS cutover**           | Custom domains, Edge DNS, certificates, and workloads can be prepared before switching production traffic.              |
| **Secure**             | **Managed HTTPS options**                       | Certificate Manager supports Let’s Encrypt, custom certificates, Azion SAN, and Trusted CA for mTLS scenarios.          |
| **Secure**             | **Unmetered DDoS protection**                   | Azion DDoS Protection is automatically enabled and unmetered across accounts.                                           |
| **Secure**             | **Integrated application security**             | WAF, Bot Manager, Network Shield, rate limiting patterns, and Firewall rules can be combined around the workload.       |
| **Store**              | **KV for low-latency application data**         | Workers KV use cases can be migrated to KV Store for configuration, feature flags, preferences, and lightweight state.  |
| **Store**              | **S3-compatible Object Storage**                | R2-style object storage workflows can be migrated using S3-compatible tools, SDKs, and credentials.                     |
| **Store**              | **Zero DTO cost for Object Storage delivery**   | Azion Object Storage does not charge Data Transfer Out over Azion’s infrastructure.                                     |
| **Store**              | **SQLite-compatible SQL Database**              | D1-style use cases can be mapped to SQL Database with familiar SQL patterns.                                            |
| **Store**              | **Vector search for AI use cases**              | SQL Database supports vector search for semantic search, recommendations, and RAG-style applications.                   |
| **Observe**            | **Real-time metrics for production visibility** | Real-Time Metrics provides near real-time monitoring through dashboards and GraphQL API.                                |
| **Observe**            | **Real-time events for investigation**          | Real-Time Events provides detailed logs for requests, functions, WAF, DNS, image processing, and other data sources.    |
| **Observe**            | **Data streaming to external tools**            | Logs can be exported to external destinations for SIEM, analytics, storage, and compliance workflows.                   |
| **Compliance**         | **Compliance-ready foundation**                 | Azion provides a stronger foundation for teams that need security, compliance alignment, and operational control.       |


With Azion, teams can build and run applications on globally distributed infrastructure while combining compute, delivery, storage, database, security, and observability capabilities in one environment. This reduces the fragmentation that often appears when modern applications depend on many separate services and configuration patterns.

Functions can interact with platform services such as KV Store and SQL Database. Applications can use Rules Engine for routing, redirects, and headers. Object Storage can support static assets, media, and user-generated files. Security capabilities can protect workloads. Real-Time Metrics and Events can give teams visibility into what is happening in production.

For engineering leaders, this means more operational clarity. For developers, it means a more cohesive workflow. For infrastructure and security teams, it means stronger control over how applications are delivered and protected. For the business, it means a platform foundation that can support growth without adding unnecessary complexity to every release cycle.

## Next Steps

After your migration is complete:

* Review [Real-Time Metrics](https://www.azion.com/en/documentation/products/observe/real-time-metrics/) to monitor application performance
* Set up [Real-Time Events](https://www.azion.com/en/documentation/products/observe/real-time-events/) for production visibility
* Configure [Web Application Firewall](https://www.azion.com/en/documentation/products/secure/firewall/web-application-firewall/) for production security
* Review the individual feature guides for advanced configuration

### Get Started with a Small Project

The best way to begin is not with the most complex application in your portfolio. Start with a project that is meaningful enough to validate the migration path, but small enough to move quickly and safely.

Choose an application or workload that includes representative pieces of your architecture: a build process, a few redirects, environment variables, maybe one function, and a manageable amount of data. Use that project to validate the workflow, document the process, and identify internal patterns your team can reuse.

From there, expand gradually. Migrate more complex routes. Move additional functions. Bring over storage and database workloads. Add observability. Review security rules. Then prepare production cutovers with greater confidence.

### Recommended Next Steps

* [Create your free Azion account](https://console.azion.com/signup)
* [Read the Applications documentation](https://www.azion.com/en/documentation/products/build/applications/)
* [Explore the Azion CLI](https://www.azion.com/en/documentation/products/azion-cli/overview/)
* [Join the Azion community](https://discord.gg/azion)

## Need Help?

Get help from [the Azion Support team](https://www.azion.com/en/documentation/), or join our [Discord community](https://discord.gg/azion) to see how others are using Azion.