# Migrate from AWS 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.

For teams using AWS, this moment often comes after years of accumulated complexity: CloudFront distributions with layered cache behaviors, Lambda functions with runtime dependencies, S3 buckets with evolving access policies, DynamoDB tables with provisioned capacity, Route 53 zones with health checks, WAF rules with managed rule groups, and CloudWatch alarms with custom metrics. Each service works, but together they create operational overhead that slows development.

For teams currently using Amazon CloudFront, AWS Lambda, Amazon S3, Amazon DynamoDB, Amazon Route 53, AWS WAF, AWS Shield, Amazon CloudWatch, or other AWS services, Azion provides equivalent capabilities through Applications, Functions, Object Storage, KV Store, Edge DNS, Web Application Firewall, DDoS Protection, Real-Time Metrics, and Real-Time Events.

The strongest reason to migrate is not simply to replace one vendor with another. It is to consolidate compute, storage, database, delivery, security, and observability into a unified platform designed for globally distributed applications.

## How AWS 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.


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, cache policies, origin configurations, 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 tables provide a comprehensive mapping of AWS products to their Azion equivalents. A dash (`-`) indicates that Azion does not currently offer a direct equivalent.

| AWS Product | Description | Azion Equivalent |
| :---------- | :---------- | :--------------- |
| **Amazon CloudFront** | AWS CDN for delivering static content, dynamic content, APIs, applications, and video globally. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) |
| **CloudFront Distributions** | Main CloudFront delivery resource for domains, origins, cache behavior, certificates, security, and edge delivery settings. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) |
| **CloudFront Alternate Domain Names** | Configure custom domains for CloudFront distributions. | [Workloads](https://www.azion.com/en/documentation/products/secure/workloads/) |
| **CloudFront Cache Behaviors** | Path-based delivery behavior, cache policy, origin request policy, allowed methods, and edge function associations. | [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) |
| **CloudFront Cache Policies** | Control cache keys, TTLs, headers, cookies, query strings, and compression. | [Cache](https://www.azion.com/en/documentation/products/build/applications/cache/) |
| **CloudFront Origin Request Policies** | Control which request values CloudFront forwards to origin. | [Rules Engine](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) |
| **CloudFront Response Headers Policies** | Add or modify response headers such as security headers and CORS headers. | [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) |
| **CloudFront Origin Shield** | Additional centralized caching layer to reduce origin load and improve cache hit ratio. | [Tiered Cache](https://www.azion.com/en/documentation/products/build/applications/cache/tiered-cache/) |
| **CloudFront Invalidation** | Remove content from CloudFront edge caches before expiration. | [Real-Time Purge](https://www.azion.com/en/documentation/products/build/applications/real-time-purge/) |
| **CloudFront Functions** | Lightweight JavaScript execution at the edge for redirects, rewrites, headers, and cache-key normalization. | [Functions for Applications](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **Lambda@Edge** | Node.js or Python functions triggered by CloudFront events to customize delivery. | [Functions for Applications](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **Lambda@Edge for security logic** | Use CloudFront-triggered functions for request validation, authentication, or blocking logic. | [Functions for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/functions/) |
| **CloudFront Device Detection** | Detect device type and pass device metadata to the origin. | [Device Groups](https://www.azion.com/en/documentation/products/build/applications/device-groups/) |
| **AWS Elemental MediaLive** | Real-time live video encoding. | [Live Ingest](https://www.azion.com/en/documentation/guides/live-ingest-best-practices/) |
| **AWS Elemental MediaPackage** | Package and originate live video streams for HLS, DASH, and related formats. | [Live Ingest](https://www.azion.com/en/documentation/guides/live-ingest-best-practices/) + [Applications](https://www.azion.com/en/documentation/products/build/applications/) |
| **CloudFront for live streaming** | Deliver live video globally using CloudFront with AWS Media Services. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) + [Live Ingest](https://www.azion.com/en/documentation/guides/live-ingest-best-practices/) |
| **AWS Lambda** | General-purpose serverless compute for event-driven code execution. | [Functions for Applications](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **Amazon API Gateway** | Create and manage REST, HTTP, and WebSocket APIs with backend integrations. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) + [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **API Gateway request validation / throttling** | Apply API request controls, throttling, and validation rules. | [Rules Engine](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) + [Firewall](https://www.azion.com/en/documentation/products/secure/firewall/) |
| **AWS Amplify Hosting** | Git-based CI/CD and hosting for static and server-side rendered web apps. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) + [Azion CLI](https://www.azion.com/en/documentation/products/azion-cli/overview/) |
| **AWS App Runner** | Deploy source code or container images to managed web applications. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) + [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **Amazon Bedrock** | Foundation model access and generative AI application development. | [AI Inference](https://www.azion.com/en/documentation/products/ai/ai-inference/) |
| **Amazon Bedrock model inference** | Invoke foundation models for text, image, embedding, and generative AI use cases. | [AI Inference](https://www.azion.com/en/documentation/products/ai/ai-inference/) |
| **Amazon Bedrock Fine-Tuning** | Customize foundation models with fine-tuning for specific use cases. | [LoRA Fine-Tune](https://www.azion.com/en/learning/ai/what-is-lora-fine-tuning/) |
| **Amazon Bedrock Custom Model Import** | Import customized foundation models into Bedrock. | [AI Inference](https://www.azion.com/en/documentation/products/ai/ai-inference/) + [LoRA Fine-Tune](https://www.azion.com/en/learning/ai/what-is-lora-fine-tuning/) |
| **Amazon SageMaker AI Real-Time Inference** | Deploy ML models to managed real-time inference endpoints. | [AI Inference](https://www.azion.com/en/documentation/products/ai/ai-inference/) |
| **Amazon S3** | Object storage for unstructured data, static assets, backups, archives, and websites. | [Object Storage](https://www.azion.com/en/documentation/products/store/object-storage/) |
| **Amazon S3 Static Website Hosting** | Host static websites from S3 buckets. | [Object Storage](https://www.azion.com/en/documentation/products/store/object-storage/) + [Applications](https://www.azion.com/en/documentation/products/build/applications/) |
| **S3 Object Lambda** | Transform S3 objects with Lambda before returning them to the requester. | [Object Storage](https://www.azion.com/en/documentation/products/store/object-storage/) + [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **S3 Object Lambda for image transformation** | Resize, watermark, redact, or transform content retrieved from S3. | [Image Processor](https://www.azion.com/en/documentation/products/build/applications/image-processor/) + [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **Amazon Aurora DSQL** | Serverless distributed relational SQL database for transactional workloads. | [SQL Database](https://www.azion.com/en/documentation/products/store/sql-database/) |
| **Amazon DynamoDB** | Serverless key-value and document database. | [KV Store](https://www.azion.com/en/documentation/products/store/kv-store/) |
| **DynamoDB Global Tables** | Multi-Region replication for globally distributed NoSQL data. | [KV Store](https://www.azion.com/en/documentation/products/store/kv-store/) |
| **AWS WAF** | Web application firewall for protecting applications and APIs. | [WAF](https://www.azion.com/en/documentation/products/secure/firewall/web-application-firewall/) / [Firewall](https://www.azion.com/en/documentation/products/secure/firewall/) |
| **AWS Managed Rules for AWS WAF** | Managed rule groups for common vulnerabilities and unwanted traffic. | [WAF Rule Sets](https://www.azion.com/en/documentation/products/secure/firewall/web-application-firewall/rules-set/) |
| **AWS WAF custom rules** | Create custom match conditions and actions for web requests. | [Rules Engine for Firewall](https://www.azion.com/en/documentation/products/secure/firewall/rules-engine/) |
| **AWS WAF Bot Control** | Managed bot detection and mitigation. | [Bot Manager](https://www.azion.com/en/documentation/products/secure/firewall/bot-manager/) |
| **AWS WAF Rate-Based Rules** | Rate limit requests based on IP, headers, URI, method, or other keys. | [Rules Engine](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) + [Network Shield](https://www.azion.com/en/documentation/products/secure/firewall/network-shield/) |
| **AWS WAF IP Sets** | Reusable IP/CIDR lists for allow or block rules. | [Network Lists](https://www.azion.com/en/documentation/products/secure/edge-firewall/network-layer-protection/network-lists/) |
| **AWS Shield Standard** | Standard DDoS protection for AWS resources. | [DDoS Protection](https://www.azion.com/en/documentation/products/secure/firewall/ddos-protection/) |
| **AWS Shield Advanced** | Advanced DDoS protection with additional visibility and mitigation options. | [DDoS Protection](https://www.azion.com/en/documentation/products/secure/firewall/ddos-protection/) |
| **Shield Advanced automatic DDoS mitigation** | Automatically creates or updates WAF protections during application-layer attacks. | [DDoS Protection](https://www.azion.com/en/documentation/products/secure/firewall/ddos-protection/) + [WAF](https://www.azion.com/en/documentation/products/secure/firewall/web-application-firewall/) |
| **AWS Network Firewall** | Managed VPC network firewall. | [Network Shield](https://www.azion.com/en/documentation/products/secure/firewall/network-shield/) |
| **Elastic Load Balancing** | Distributes traffic across multiple targets and availability zones. | [Load Balancer](https://www.azion.com/en/documentation/products/secure/connectors/load-balancer/) |
| **Application Load Balancer** | Layer 7 HTTP/HTTPS load balancing with application-level routing. | [Load Balancer](https://www.azion.com/en/documentation/products/secure/connectors/load-balancer/) |
| **Network Load Balancer** | Layer 4 TCP/UDP/TLS load balancing. | [Load Balancer](https://www.azion.com/en/documentation/products/secure/connectors/load-balancer/) |
| **AWS Global Accelerator** | Global Anycast IPs and optimized routing over the AWS global network. | [Applications](https://www.azion.com/en/documentation/products/build/applications/) + [Load Balancer](https://www.azion.com/en/documentation/products/secure/connectors/load-balancer/) |
| **CloudFront Origin Access Control** | Secure S3 origins so users access content through CloudFront instead of directly from S3. | [Connectors](https://www.azion.com/en/documentation/products/secure/connectors/) + [Origin Shield](https://www.azion.com/en/documentation/products/secure/connectors/origin-shield/) |
| **CloudFront Signed URLs / Signed Cookies** | Restrict access to private content using signed URLs or cookies. | [Rules Engine](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) + [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/) |
| **CloudFront Geographic Restrictions** | Allow or block content access by country. | [Rules Engine](https://www.azion.com/en/documentation/products/build/applications/rules-engine/) + [Network Shield](https://www.azion.com/en/documentation/products/secure/firewall/network-shield/) |
| **Amazon Route 53** | Authoritative DNS, domain registration, routing policies, and health checks. | [Edge DNS](https://www.azion.com/en/documentation/products/secure/edge-dns/) |
| **AWS Certificate Manager** | Provision, import, manage, deploy, and renew SSL/TLS certificates. | [Certificate Manager](https://www.azion.com/en/documentation/products/secure/firewall/certificate-manager/) |
| **AWS Private CA** | Create and operate private certificate authorities. | [Certificate Manager](https://www.azion.com/en/documentation/products/secure/firewall/certificate-manager/) |
| **AWS Private CA for client authentication** | Private PKI patterns for certificate-based client authentication. | [mTLS](https://www.azion.com/en/documentation/products/secure/firewall/mtls/) |
| **AWS IoT Greengrass** | Run AWS-managed edge components and local processing on edge devices. | [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **AWS IoT Greengrass deployments** | Deploy components and configurations to edge devices. | [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **Amazon ECS Anywhere** | Register and manage on-premises or external servers in ECS clusters. | [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **AWS Outposts** | Run AWS infrastructure and services on customer premises. | [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **AWS Systems Manager Hybrid Activations** | Manage non-EC2 machines in hybrid and multicloud environments. | [Orchestrator](https://www.azion.com/en/products/orchestrator/) |
| **Amazon CloudWatch Metrics** | Collect, query, visualize, and alarm on service and application metrics. | [Real-Time Metrics](https://www.azion.com/en/documentation/products/observe/real-time-metrics/) |
| **Amazon CloudWatch Logs** | Collect, monitor, query, and analyze logs. | [Real-Time Events](https://www.azion.com/en/documentation/products/observe/real-time-events/) |
| **CloudWatch Logs Insights** | Query and investigate logs interactively. | [Real-Time Events](https://www.azion.com/en/documentation/products/observe/real-time-events/) |
| **Amazon Data Firehose** | Deliver streaming data to destinations such as S3, Redshift, OpenSearch, and HTTP endpoints. | [Data Stream](https://www.azion.com/en/documentation/products/observe/data-stream/) |
| **CloudWatch RUM** | Real user monitoring for browser and mobile application performance. | [Edge Pulse](https://www.azion.com/en/documentation/products/observe/edge-pulse/) |
| **AWS Marketplace** | Discover, buy, deploy, and manage third-party software, data, and services. | [Marketplace](https://www.azion.com/en/documentation/products/marketplace/) |
| **AWS Management Console** | Web interface for accessing and managing AWS services. | [Azion Console](https://console.azion.com/) |
| **AWS APIs** | Programmatic interface for AWS service operations. | [Azion API](https://www.azion.com/en/documentation/products/overview-azion-api/) |
| **Amazon CloudWatch APIs / Metrics APIs** | Query metrics, logs, alarms, and observability data programmatically. | [GraphQL API](https://www.azion.com/en/documentation/devtools/graphql-api/) |
| **AWS CLI** | Command-line interface for managing AWS services. | [Azion CLI](https://www.azion.com/en/documentation/products/azion-cli/overview/) |
| **AWS SDKs** | Language-specific SDKs for building integrations with AWS services. | [SDK](https://www.azion.com/en/documentation/devtools/sdk/go/) |
| **AWS SDK for JavaScript** | JavaScript libraries for interacting with AWS services. | [Azion Lib](https://www.azion.com/en/documentation/products/azion-lib/overview/) |
| **AWS CloudFormation** | Infrastructure as Code service for modeling and provisioning AWS resources. | [Terraform Provider](https://www.azion.com/en/documentation/products/terraform-provider/) |
| **AWS Cloud Development Kit** | Define infrastructure using programming languages and synthesize to CloudFormation. | [Terraform Provider](https://www.azion.com/en/documentation/products/terraform-provider/) + [Azion API](https://www.azion.com/en/documentation/products/overview-azion-api/) |
| **Terraform AWS Provider** | Terraform provider for managing AWS resources. | [Terraform Provider](https://www.azion.com/en/documentation/products/terraform-provider/) |
| **Lambda runtime environment** | Runtime layer used by Lambda functions. | [Azion Runtime](https://www.azion.com/en/documentation/runtime/overview/) |
| **CloudFront edge runtime** | Runtime environment for CloudFront Functions and Lambda@Edge. | [Azion Runtime](https://www.azion.com/en/documentation/runtime/overview/) |

## 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 Lambda functions, CloudFront behaviors, routing, headers, load balancing, cache, image optimization, and AI workloads.
- **Secure**: migrate custom domains, Route 53 DNS, SSL/TLS certificates, WAF rules, DDoS protection, bot management, and rate limiting.
- **Store**: migrate S3 objects, DynamoDB tables, and Aurora databases to Object Storage, KV Store, and SQL Database.
- **Observe**: migrate CloudWatch metrics, logs, and alarms 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 on AWS. If you have used AWS CloudFormation, SAM, or CDK, you already understand the pattern: define infrastructure as code, configure build settings, 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 | AWS | Azion |
| :----- | :--- | :---- |
| **Config file** | `template.yaml` (SAM) / `cdk.json` (CDK) | `azion.config.js` (JavaScript) |
| **Framework detection** | Manual configuration | 20+ frameworks with auto-detection |
| **Cold starts** | Common (regional Lambda) | Minimized (distributed nodes) |
| **Compliance** | SOC 2, ISO 27001, HIPAA | 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 distribution, function, API gateway, 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 | AWS CLI | Azion CLI |
| :--- | :------ | :-------- |
| **Install** | `pip install awscli` | `curl -fsSL https://cli.azion.app/install.sh \| bash` |
| **Login** | `aws configure` | `azion login` |
| **Local dev** | `sam local start-api` | `azion dev` |
| **Deploy** | `sam deploy --guided` or `cdk deploy` | `azion deploy` |
| **View logs** | `aws logs tail /aws/lambda/my-function` | `azion logs` |

#### Build Configuration Comparison

| Aspect | AWS SAM/CDK | Azion |
| :----- | :---------- | :---- |
| **Infrastructure as Code** | YAML/TypeScript templates | JavaScript config |
| **Local testing** | SAM local emulator | Built-in dev server |
| **Deployment** | CloudFormation stacks | Direct deployment |
| **Rollback** | Stack rollback | Version history |

#### 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 | AWS | Azion |
| :----- | :-- | :---- |
| **Access** | `process.env.VARIABLE` | `Azion.env.get('VARIABLE')` |
| **Secrets management** | AWS Secrets Manager / Systems Manager Parameter Store | Variables in Functions Instances |
| **Environment stages** | Stage name in function ARN | Environment context in config |

#### Evaluate Your Variables

Before changing code, identify every variable in:

* AWS Lambda: Environment variables in function configuration
* AWS Secrets Manager: Secret values and rotation policies
* Systems Manager Parameter Store: Parameters and paths
* Elastic Beanstalk: Environment properties
* CI/CD environment settings (CodePipeline, CodeBuild)
* 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: AWS Lambda / Node.js
const apiKey = process.env.API_KEY;
const dbHost = process.env.DB_HOST;

// Before: AWS with Secrets Manager (async)
const { SecretsManager } = require('@aws-sdk/client-secrets-manager');
const client = new SecretsManager();
const secret = await client.getSecretValue({ SecretId: 'my-secret' });
const secretValue = JSON.parse(secret.SecretString);

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

:::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 CloudFront to Applications

CloudFront distributions deliver content from edge locations with caching and origin configuration. Azion Applications provide similar capabilities with integrated Rules Engine for request/response manipulation.

#### Key Differences

| Aspect | AWS CloudFront | Azion Applications |
| :----- | :------------- | :----------------- |
| **Distribution config** | XML/JSON in CloudFormation | JavaScript config or Console |
| **Origins** | S3, ALB, Custom origins | Connectors (HTTP, Object Storage) |
| **Behaviors** | Cache behaviors with paths | Rules Engine with criteria |
| **SSL certificates** | ACM (us-east-1 only) | Digital Certificates |
| **Lambda@Edge** | Edge functions (4 triggers) | Functions (request/response phases) |

#### 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. Navigate to **Build > Applications**.
3. Click **Add Application**.
4. Configure your **Main Settings**:
   - Name your application
   - Set origin type (HTTP, Object Storage)
   - Configure origin address
5. Set up **Cache Settings** for TTL configuration.
6. Configure **Rules Engine** for path-based routing.
7. Add **Custom Domains** when ready.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
curl -X POST 'https://api.azionapi.net/v4/workspace/applications' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "my-app",
    "origins": [
      {
        "name": "origin-main",
        "addresses": [
          {
            "address": "origin.example.com",
            "weight": 1
          }
        ]
      }
    ],
    "cache_settings": {
      "default_ttl": 3600
    }
  }'
`} />
</Fragment>
</Tabs>

#### Distribution Configuration Migration

<Code lang="javascript" code={`
// CloudFront distribution config (CloudFormation YAML converted to Azion JS)
import { defineConfig } from 'azion'

export default defineConfig({
  name: 'my-distribution',
  applications: [{
    name: 'main-app',
    origins: [{
      name: 's3-origin',
      type: 'object_storage',
      addresses: [{
        address: 'my-bucket.azionedge.net',
        weight: 1
      }]
    }],
    cache: {
      ttl: 86400,
      staleWhileRevalidate: 300
    },
    rules: {
      request: [{
        name: 'API Routes',
        criteria: [{
          variable: 'uri',
          operator: 'starts_with',
          argument: '/api/'
        }],
        behavior: {
          bypassCache: true,
          runFunction: 'api-handler'
        }
      }]
    }
  }]
})
`} />

#### Origin Request vs Viewer Request

In CloudFront, Lambda@Edge functions trigger at different points. Azion maps these to Rules Engine phases:

| CloudFront Trigger | Azion Equivalent |
| :----------------- | :--------------- |
| Viewer Request | Rules Engine > Request Phase |
| Origin Request | Rules Engine > Request Phase (after cache check) |
| Origin Response | Rules Engine > Response Phase |
| Viewer Response | Rules Engine > Response Phase |

#### Reference documentation

* [Applications](https://www.azion.com/en/documentation/products/build/applications/)
* [Applications Main Settings](https://www.azion.com/en/documentation/products/build/applications/main-settings/)
* [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/)
* [Connectors](https://www.azion.com/en/documentation/products/secure/connectors/)

### 5. Migrating API Gateway to Applications + Functions

API Gateway provides REST and HTTP API management with authorizers, throttling, and stage management. Azion Applications combined with Functions deliver similar capabilities with distributed execution.

#### Key Differences

| Aspect | AWS API Gateway | Azion Applications + Functions |
| :----- | :-------------- | :----------------------------- |
| **API types** | REST API, HTTP API | Functions with routing |
| **Authorizers** | Lambda, Cognito, JWT | Functions with custom logic |
| **Stages** | Stage variables and deployments | Environment configuration |
| **Throttling** | Usage plans + rate limiting | Rate Limit rules |
| **Custom domains** | Domain mappings | Application domains |

#### 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. Navigate to **Build > Functions**.
3. Create Functions for each API endpoint.
4. Navigate to **Build > Applications**.
5. Create an Application for your API.
6. Configure **Rules Engine** to route paths to Functions.
7. Set up rate limiting rules.
8. Add authentication via Functions.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a Function
curl -X POST 'https://api.azionapi.net/v4/workspace/functions' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "api-handler",
    "code": "export default { async fetch(request) { return new Response(JSON.stringify({ message: \"Hello\" }), { headers: { \"Content-Type\": \"application/json\" } }); } }"
  }'

# Create Application with routing rules
curl -X POST 'https://api.azionapi.net/v4/workspace/applications' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "api-gateway",
    "rules": {
      "request": [{
        "name": "API Route",
        "criteria": [{ "variable": "uri", "operator": "starts_with", "argument": "/api/" }],
        "behavior": { "runFunction": "api-handler" }
      }]
    }
  }'
`} />
</Fragment>
</Tabs>

#### API Gateway Authorizer Migration

<Code lang="javascript" code={`
// Before: AWS Lambda Authorizer
exports.handler = async (event) => {
  const token = event.authorizationToken;
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    return {
      principalId: decoded.sub,
      policyDocument: {
        Version: '2012-10-17',
        Statement: [{
          Action: 'execute-api:Invoke',
          Effect: 'Allow',
          Resource: event.methodArn
        }]
      }
    };
  } catch (err) {
    throw new Error('Unauthorized');
  }
};

// After: Azion Function for Authorization
export default {
  async fetch(request) {
    const authHeader = request.headers.get('Authorization');
    if (!authHeader) {
      return new Response('Unauthorized', { status: 401 });
    }

    const token = authHeader.replace('Bearer ', '');
    try {
      const secret = Azion.env.get('JWT_SECRET');
      const decoded = await verifyJWT(token, secret);

      // Store user info in request metadata for downstream functions
      request.metadata['user_id'] = decoded.sub;
      return request; // Continue to next handler
    } catch (err) {
      return new Response('Unauthorized', { status: 401 });
    }
  }
};
`} />

#### Route Migration Example

<Code lang="javascript" code={`
// API Gateway routes → Azion Rules Engine

// Before: API Gateway resource paths
// GET /users/{id}
// POST /users
// PUT /users/{id}
// DELETE /users/{id}

// After: Azion Rules Engine configuration
import { defineConfig } from 'azion'

export default defineConfig({
  applications: [{
    name: 'api-app',
    rules: {
      request: [
        {
          name: 'GET /users/:id',
          criteria: [
            { variable: 'uri', operator: 'matches_regex', argument: '^/users/([0-9]+)$' },
            { variable: 'request_method', operator: 'equals', argument: 'GET' }
          ],
          behavior: { runFunction: 'get-user' }
        },
        {
          name: 'POST /users',
          criteria: [
            { variable: 'uri', operator: 'equals', argument: '/users' },
            { variable: 'request_method', operator: 'equals', argument: 'POST' }
          ],
          behavior: { runFunction: 'create-user' }
        }
      ]
    }
  }]
})
`} />

#### 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/)
* [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/)

### 6. Migrating Lambda 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 | AWS Lambda | Azion Functions |
| :----- | :--------- | :-------------- |
| **Function signature** | `exports.handler = async (event) => {}` | `export default { async fetch(request) {} }` |
| **Runtime** | Node.js, Python, Java, Go, .NET, Ruby | JavaScript (V8 isolates) |
| **Memory** | 128 MB - 10,240 MB | 512 MB (default) |
| **Timeout** | 1 sec - 15 min | Configurable per execution |
| **Cold starts** | Common (regional, VPC-cold) | Minimized (distributed nodes) |
| **Event sources** | SQS, SNS, Kinesis, DynamoDB, API Gateway | HTTP requests, scheduled triggers |

#### Update Function Signature

<Code lang="javascript" code={`
// Before: AWS Lambda
exports.handler = async (event) => {
  const body = JSON.parse(event.body);
  const pathParams = event.pathParameters;
  const queryParams = event.queryStringParameters;

  // Process request
  return {
    statusCode: 200,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ message: 'Hello', data: body })
  };
};

// After: Azion Functions
export default {
  async fetch(request) {
    const body = await request.json();
    const url = new URL(request.url);
    const queryParams = Object.fromEntries(url.searchParams);

    // Process request
    return new Response(JSON.stringify({ message: 'Hello', data: body }), {
      status: 200,
      headers: { 'Content-Type': 'application/json' }
    });
  }
};
`} />

#### Event Context Migration

<Code lang="javascript" code={`
// Before: AWS Lambda event context
exports.handler = async (event, context) => {
  const requestId = context.awsRequestId;
  const functionName = context.functionName;
  const remainingTime = context.getRemainingTimeInMillis();

  // Request metadata from API Gateway
  const sourceIp = event.requestContext.identity.sourceIp;
  const userAgent = event.requestContext.identity.userAgent;
  const country = event.headers['CloudFront-Viewer-Country'];

  return { statusCode: 200, body: 'OK' };
};

// After: Azion Functions
export default {
  async fetch(request, env, ctx) {
    // Request metadata
    const requestId = request.headers.get('x-request-id');
    const userAgent = request.headers.get('user-agent');
    const country = request.metadata['geoip_country_code'];
    const city = request.metadata['geoip_city'];

    // Geo metadata available directly
    const region = request.metadata['geoip_region'];

    return new Response('OK', { status: 200 });
  }
};
`} />

#### Environment Variables Migration

<Code lang="javascript" code={`
// Before: AWS Lambda
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;

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

#### Cold Start Comparison

AWS Lambda cold starts vary significantly based on runtime, memory allocation, and VPC configuration. Azion Functions minimize cold starts through distributed node placement:

| Scenario | AWS Lambda Cold Start | Azion Functions Cold Start |
| :------- | :-------------------- | :------------------------- |
| Node.js (no VPC) | 100-300ms | Minimal |
| Node.js (with VPC) | 500ms-2s | N/A (no VPC concept) |
| Java/Spring | 1-5s | N/A |
| Python | 100-500ms | N/A |

:::note
Azion Functions use V8 isolates (JavaScript runtime), providing consistent performance without the cold start variability of container-based Lambda. If you have Lambda functions in Java, Python, or other runtimes, you will need to rewrite them in JavaScript.
:::

#### 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/)

### 7. Migrating Load Balancing (ALB/NLB to Load Balancer)

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

#### Key Differences

| Aspect | AWS ALB/NLB | Azion Load Balancer |
| :----- | :---------- | :------------------ |
| **Health checks** | HTTP, HTTPS, TCP | HTTP, HTTPS, TCP |
| **Steering policies** | Round-robin, Least connections, IP hash | Round-robin, Least connections, Geo |
| **Failover** | Target group failover | Origin-level failover |
| **Session affinity** | Cookie, IP hash | Cookie, IP hash |
| **Targets** | EC2, Lambda, IP addresses | Connectors (origins) |
| **Protocol** | Layer 4 (NLB), Layer 7 (ALB) | Layer 7 (HTTP/HTTPS) |

#### 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** > **Connectors**.
3. Create a **Connector** for each origin server.
4. Configure health checks for each origin.
5. In your **Application**, configure origins with load balancing settings.
6. Set origin weights for weighted distribution.
7. Enable session affinity if needed.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a Connector with multiple addresses for load balancing
curl -X POST 'https://api.azionapi.net/v4/workspace/connectors' \
  --header 'Authorization: Token YOUR_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Origin-Pool-US",
    "type": "http",
    "attributes": {
      "addresses": [
        {
          "address": "us-east-origin1.example.com",
          "active": true,
          "modules": {
            "load_balancer": {
              "weight": 3,
              "method": "round_robin"
            }
          }
        },
        {
          "address": "us-east-origin2.example.com",
          "active": true,
          "modules": {
            "load_balancer": {
              "weight": 1,
              "method": "round_robin"
            }
          }
        }
      ]
    }
  }'
`} />
</Fragment>
</Tabs>

#### Load Balancer Module Configuration

<Code lang="javascript" code={`
// Load balancer settings within Connector 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 on failure
  "connection_timeout": 10,       // Connection timeout in seconds
  "read_write_timeout": 30        // Read/write timeout in seconds
}
`} />

#### ALB Target Group Migration

| AWS ALB Config | Azion Equivalent |
| :------------- | :--------------- |
| Target Group | Connector |
| Health Check Path | Connector health check path |
| Health Check Interval | Connector health check interval |
| Healthy Threshold | Health check success threshold |
| Unhealthy Threshold | Health check failure threshold |

#### 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/)
* [Application Main Settings](https://www.azion.com/en/documentation/products/build/applications/main-settings/)

### 8. Migrating Cache Configuration

Caching configuration determines how content is stored and served from node locations. Azion Cache provides fine-grained control with Tiered Cache support for improved hit ratios.

#### Key Differences

| Aspect | AWS CloudFront Cache | Azion Cache |
| :----- | :------------------- | :---------- |
| **Cache levels** | Regional edge caches + Edge locations | Tiered Cache + Cache + Browser Cache |
| **Cache key** | Cache policy + origin request policy | Customizable via Rules Engine |
| **Purge** | Invalidations (path-based) | URL, Cache Key, Wildcard purge |
| **Stale content** | Origin shield, stale-while-revalidate | Stale-while-revalidate |
| **TTL limits** | Default 24h, max 1 year | Per-rule configuration |

#### CloudFront Cache Policies to Azion Cache Settings

| CloudFront Cache Policy | Azion Equivalent |
| :---------------------- | :--------------- |
| CachingOptimized | Default Cache Settings with high TTL |
| CachingDisabled | Bypass Cache behavior in Rules Engine |
| Elemental-MediaPackage | Custom Cache Settings for streaming |
| Custom policy | Cache Settings + Rules Engine |

#### 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 **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 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>

#### Cache Key Customization

In CloudFront, cache keys are defined by cache policies. In Azion, use **Advanced Cache Key** in Cache Settings:

**Example: Vary cache by query strings**

<Code lang="javascript" code={`
// In Cache Settings
{
  "name": "api-cache",
  "cache_key": {
    "query_string": {
      "include_all": false,
      "include": ["version", "lang"]
    }
  }
}
`} />

#### CloudFront Invalidation to Azion Purge

<Code lang="bash" code={`
# Before: AWS CloudFront invalidation
aws cloudfront create-invalidation \
  --distribution-id E123456789ABCD \
  --paths "/images/*" "/css/*"

# After: Azion cache purge
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/*",
      "https://example.com/css/*"
    ],
    "layer": "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/)

### 9. Migrating Image Optimization

Image optimization reduces image file sizes while maintaining visual quality. Azion Image Processor transforms, optimizes, and delivers images from the distributed locations with automatic format selection.

#### Key Differences

| Aspect | AWS CloudFront + Lambda@Edge | Azion Image Processor |
| :----- | :-------------------------- | :-------------------- |
| **Storage** | S3 origin | Object Storage integration |
| **Transformations** | Custom Lambda@Edge | Built-in transformations |
| **URL format** | Custom implementation | `?ims=<OPTIONS>` query parameter |
| **Format support** | Custom implementation | WebP, AVIF, JPEG, PNG |
| **Signed URLs** | CloudFront signed URLs | Secure Token |

#### URL Format Comparison

<Code lang="text" code={`
# AWS CloudFront (requires Lambda@Edge or custom origin)
# Typically custom URL structure:
https://d12345.cloudfront.net/images/photo.jpg?w=400&q=80

# Azion Image Processor
https://example.com/images/photo.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` |

#### 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>

:::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 (Bedrock 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 at the distributed infrastructure.

#### Key Differences

| Aspect | AWS Bedrock | Azion AI Inference |
| :----- | :---------- | :----------------- |
| **Model access** | Managed foundation models | Custom model deployment |
| **Inference API** | Bedrock Runtime API | REST API + Functions |
| **Model types** | Claude, Llama, Titan, Stable Diffusion | Custom models, LLMs |
| **GPU support** | Managed infrastructure | Dedicated GPU instances |
| **Pricing** | Per-token / per-image | Per-inference |

#### 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 **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 Azion Functions
export default {
  async fetch(request) {
    const body = await request.json();

    // Call AI inference endpoint
    const response = await fetch('https://ai-inference.azion.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: body.prompt,
        max_tokens: 100
      })
    });

    return response;
  }
};
`} />
</Fragment>
</Tabs>

#### Bedrock to Azion Migration Example

<Code lang="javascript" code={`
// Before: AWS Bedrock
import { BedrockRuntime } from '@aws-sdk/client-bedrock-runtime';

const client = new BedrockRuntime({ region: 'us-east-1' });

const response = await client.invokeModel({
  modelId: 'anthropic.claude-3-sonnet-20240229-v1:0',
  contentType: 'application/json',
  accept: 'application/json',
  body: JSON.stringify({
    anthropic_version: 'bedrock-2023-05-31',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello, world!' }]
  })
});

// After: Azion AI Inference
export default {
  async fetch(request) {
    const response = await fetch('https://ai-inference.azion.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': \`Bearer \${Azion.env.get('AI_API_KEY')}\`
      },
      body: JSON.stringify({
        model: 'claude-3-sonnet',
        messages: [{ role: 'user', content: 'Hello, world!' }],
        max_tokens: 1024
      })
    });

    return response;
  }
};
`} />

#### 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/)

### 11. Migrating Orchestration (Step Functions, EventBridge)

AWS Step Functions and EventBridge provide workflow orchestration and event routing. Azion achieves similar patterns through Functions chaining and Data Streaming for event-driven architectures.

#### Key Differences

| Aspect | AWS Step Functions | Azion Functions Chaining |
| :----- | :----------------- | :---------------------- |
| **Workflow definition** | ASL (Amazon States Language) | JavaScript/TypeScript |
| **State management** | Built-in state machine | Custom implementation |
| **Error handling** | Retry, catch, fallback | Try/catch in Functions |
| **Visualization** | Workflow Studio | Code-based |

| Aspect | AWS EventBridge | Azion Data Streaming |
| :----- | :-------------- | :------------------- |
| **Event routing** | Rules and targets | Data Streaming + Functions |
| **Event patterns** | Pattern matching | Custom Functions logic |
| **Targets** | 100+ AWS services | HTTP endpoints, Functions |

#### Step Functions to Functions Chaining

<Code lang="javascript" code={`
// Before: AWS Step Functions (ASL)
{
  "Comment": "Order processing workflow",
  "StartAt": "ValidateOrder",
  "States": {
    "ValidateOrder": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789:function:validate-order",
      "Next": "ProcessPayment"
    },
    "ProcessPayment": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789:function:process-payment",
      "Catch": [{
        "ErrorEquals": ["PaymentFailed"],
        "Next": "NotifyFailure"
      }],
      "Next": "FulfillOrder"
    },
    "FulfillOrder": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789:function:fulfill-order",
      "End": true
    },
    "NotifyFailure": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789:function:notify-failure",
      "End": true
    }
  }
}

// After: Azion Functions (orchestrator pattern)
// orchestrator.js
export default {
  async fetch(request) {
    const order = await request.json();

    try {
      // Step 1: Validate
      const validated = await validateOrder(order);

      // Step 2: Process payment
      const payment = await processPayment(validated);

      // Step 3: Fulfill order
      const fulfillment = await fulfillOrder(payment);

      return new Response(JSON.stringify(fulfillment), {
        headers: { 'Content-Type': 'application/json' }
      });
    } catch (error) {
      // Error handling
      await notifyFailure({ order, error: error.message });
      return new Response(JSON.stringify({ error: error.message }), {
        status: 500,
        headers: { 'Content-Type': 'application/json' }
      });
    }
  }
};

// Individual function modules
async function validateOrder(order) {
  // Validation logic
  if (!order.items || order.items.length === 0) {
    throw new Error('Invalid order: no items');
  }
  return { ...order, validated: true };
}

async function processPayment(order) {
  // Payment processing
  const response = await fetch('https://payment-api.example.com/charge', {
    method: 'POST',
    body: JSON.stringify({ amount: order.total, currency: 'USD' })
  });

  if (!response.ok) {
    throw new Error('PaymentFailed');
  }

  return { ...order, paid: true };
}

async function fulfillOrder(order) {
  // Fulfillment logic
  return { ...order, fulfilled: true, fulfilledAt: new Date().toISOString() };
}

async function notifyFailure(context) {
  // Send failure notification
  await fetch('https://notifications.example.com/failure', {
    method: 'POST',
    body: JSON.stringify(context)
  });
}
`} />

#### EventBridge to Data Streaming

<Code lang="javascript" code={`
// Before: AWS EventBridge rule
{
  "source": ["com.mycompany.orders"],
  "detail-type": ["OrderCreated"],
  "detail": {
    "amount": [{ "numeric": [">", 100] }]
  }
}

// Target: Lambda function for processing

// After: Azion Data Streaming + Functions
// Configure Data Streaming to send events to your Function endpoint
// Then process in Function:

export default {
  async fetch(request) {
    const events = await request.json();

    for (const event of events) {
      if (event.source === 'com.mycompany.orders' &&
          event.type === 'OrderCreated' &&
          event.data.amount > 100) {
        // Process high-value order
        await processHighValueOrder(event.data);
      }
    }

    return new Response('OK');
  }
};
`} />

#### Reference documentation

* [Functions](https://www.azion.com/en/documentation/products/build/applications/functions/)
* [Data Streaming](https://www.azion.com/en/documentation/products/observe/data-streaming/)


## 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 Route 53 as 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">
Update your Route 53 hosted zone to point the subdomain to Azion:

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

This keeps Route 53 as your DNS provider while routing traffic through Azion.
</Fragment>

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

<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 from Route 53 to Edge DNS requires careful planning to avoid downtime during the nameserver switch.

#### Key Differences

| Aspect | Route 53 | Azion Edge DNS |
| :----- | :------- | :------------- |
| **Nameservers** | Assigned per hosted zone | `ns1.aziondns.net`, `ns2.aziondns.com`, `ns3.aziondns.org` |
| **Record types** | A, AAAA, CNAME, MX, TXT, SRV, NS, SOA, PTR, CAA | A, AAAA, CNAME, MX, TXT, SRV, NS, CAA, PTR |
| **Routing policies** | Simple, Weighted, Latency, Failover, Geolocation | Round-robin, Geo |
| **Health checks** | Route 53 health checks | Connector health checks |
| **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 Route 53 configuration.
6. Note the Azion nameservers assigned to your zone.
7. Update nameservers at your domain registrar (not in Route 53).
</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

| Route 53 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 |
| PTR | PTR | Reverse DNS lookup |

#### Routing Policy Migration

| Route 53 Policy | Azion Equivalent | Implementation |
| :-------------- | :--------------- | :------------- |
| Simple | Standard record | Single record with one or more values |
| Weighted | Not directly supported | Use Functions for custom logic |
| Latency | Not directly supported | Applications handles routing |
| Failover | Not directly supported | Configure via Rules Engine |
| Geolocation | Geo routing | Available in Edge DNS |

#### 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 domain 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

# Compare Route 53 and Azion records
dig @ns-1234.awsdns-12.com example.com A
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 from AWS Certificate Manager (ACM).

#### Key Differences

| Area | AWS Certificate Manager | Azion Certificate Manager |
| :--- | :---------------------- | :------------------------ |
| **Certificate types** | Public, Private, Imported | Let's Encrypt, Custom, Azion SAN |
| **Validation** | DNS, Email | DNS-01, HTTP-01 |
| **Renewal** | Automatic | Automatic (Let's Encrypt) |
| **Scope** | Regional (us-east-1 for CloudFront) | Global Network |
| **mTLS** | Supported (Private CA) | Supported (Trusted CA) |
| **Cost** | Free for AWS resources | Free (Let's Encrypt) |

#### 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 from ACM or external CAs:

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

<Fragment slot="panel.console">
1. Export your certificate from ACM (if applicable).
2. Go to **Products menu** > **Certificate Manager**.
3. Click **+ Certificate**.
4. Select **Custom Certificate**.
5. Upload your certificate (PEM format).
6. Upload your private key.
7. Upload intermediate CA chain (if applicable).
8. 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.

:::note
ACM Private CA certificates can be exported and uploaded to Azion as Trusted CA certificates for mTLS configuration.
:::

#### 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 AWS WAF rules requires careful mapping of rule logic and understanding differences in rule construction.

#### Key Differences

| Aspect | AWS WAF | Azion WAF |
| :----- | :------ | :-------- |
| **Rule language** | JSON-based rules | Rules Engine criteria |
| **Managed rules** | AWS Managed Rules, Marketplace rules | Azion-managed rulesets |
| **Custom rules** | Web ACL with rules | Rules Engine for Firewall |
| **OWASP coverage** | Core rule set via managed rules | OWASP Top 10 coverage |
| **Scope** | Regional or CloudFront | Global Network |
| **Mode options** | Count, Block | 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 AWS WAF rule to Azion Rules Engine:

**AWS WAF JSON rule:**
<Code lang="json" code={`
{
  "Name": "BlockAdminAccess",
  "Priority": 1,
  "Statement": {
    "AndStatement": {
      "Statements": [
        {
          "ByteMatchStatement": {
            "SearchString": "/admin",
            "FieldToMatch": { "UriPath": {} },
            "PositionalConstraint": "CONTAINS"
          }
        },
        {
          "NotStatement": {
            "Statement": {
              "IPSetReferenceStatement": { "IPSet": "allowed-ips" }
            }
          }
        }
      ]
    }
  },
  "Action": { "Block": {} }
}
`} />

**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.
:::

#### AWS Managed Rules to Azion Rulesets Mapping

| AWS Managed Rule Group | Azion Equivalent |
| :--------------------- | :--------------- |
| AWSManagedRulesCommonRuleSet | General Attack Detection |
| AWSManagedRulesSQLiRuleSet | SQL Injection ruleset |
| AWSManagedRulesXSSRuleSet | XSS ruleset |
| AWSManagedRulesLinuxRuleSet | OS Command Injection |
| AWSManagedRulesPHPAppRuleSet | Included in General Detection |

#### 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 | AWS Shield | Azion DDoS Protection |
| :----- | :--------- | :-------------------- |
| **Standard protection** | Automatic, no cost | Automatic, no cost |
| **Advanced protection** | AWS Shield Advanced (additional cost) | Managed rules + Rules Engine |
| **Layer coverage** | L3, L4, L7 | L3, L4, L7 |
| **DDoS response team** | Shield Advanced only | Enterprise support |
| **Cost protection** | Shield Advanced includes cost protection | Standard protection |

#### 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 | AWS Bot Control | Azion Bot Manager |
| :----- | :-------------- | :---------------- |
| **Detection** | Machine learning, heuristics, fingerprinting | Machine learning, behavioral analysis, fingerprinting, Reputation Intelligence |
| **Challenge** | CAPTCHA, silent challenge | JavaScript injection (fingerprinting), ALTCHA (via redirect) |
| **Actions** | Allow, Count, Block, CAPTCHA | Allow, Deny, Drop, Redirect, Custom HTML, Random Delay, Hold Connection |
| **Lite version** | Not available | 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 | AWS WAF Rate Limiting | Azion Rate Limiting |
| :----- | :-------------------- | :----------------- |
| **Configuration** | Rate-based rules in Web ACL | Firewall rules + Functions |
| **Granularity** | Path, method, IP, header | Path, method, IP, custom |
| **Actions** | Block, Count | Block, Log |
| **Window** | 1 minute to 1 hour | Customizable |
| **Scope** | Regional or CloudFront | Global Network |

#### 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/)

### 8. Migrating Security Services

AWS provides multiple security services for threat detection and vulnerability management. Azion offers comparable protection through Firewall and Network Lists.

#### Key Differences

| Aspect | AWS Security Services | Azion Equivalent |
| :----- | :-------------------- | :--------------- |
| **Threat detection** | GuardDuty | Firewall + Network Lists |
| **Vulnerability scanning** | Inspector | External scanning + Firewall |
| **Security Hub** | Centralized findings | Real-Time Events + Firewall logs |
| **Threat intelligence** | GuardDuty threat feeds | Network Lists (Tor, known malicious IPs) |

#### Network Lists for Threat Intelligence

Azion provides Network Lists that include threat intelligence data:

<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** > **Network Lists**.
3. View available Azion-maintained lists:
   * **Tor Nodes**: Known Tor exit nodes
   * **Malicious IPs**: Known malicious IP addresses
   * **Geo-blocking**: Country-based lists
4. Create custom lists for your specific needs.
5. Reference lists in Firewall rules.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a custom network list
curl -X POST 'https://api.azionapi.net/v4/workspace/network_lists' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "Blocked IPs",
    "list_type": "ip_cidr",
    "items": ["192.168.1.0/24", "10.0.0.1"]
  }'

# Use network list in firewall 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": "Block Malicious IPs",
    "criteria": [[{"variable": "\${remote_addr}", "operator": "is_in_network_list", "argument": "network_list_id"}]],
    "behaviors": [{"type": "deny", "attributes": {"status_code": 403}}]
  }'
`} />
:::note
Network Lists are created via `/v4/workspace/network_lists`. Use the list ID in Firewall rules with the `is_in_network_list` operator to block traffic from known malicious sources.
:::
</Fragment>
</Tabs>

#### Migration Considerations

When migrating from AWS security services:

1. **GuardDuty findings**: Export findings and create corresponding Firewall rules for IP-based threats.
2. **Inspector vulnerabilities**: Address application vulnerabilities before migration; Azion WAF provides runtime protection.
3. **CloudTrail logs**: Configure Real-Time Events for comparable visibility.
4. **Security Hub**: Use Azion Real-Time Events and external SIEM integration.

#### Reference documentation

* [Network Lists](https://www.azion.com/en/documentation/products/secure/edge-firewall/network-layer-protection/network-lists/)
* [Real-Time Events](https://www.azion.com/en/documentation/products/observe/real-time-events/)
* [Data Streaming](https://www.azion.com/en/documentation/products/observe/data-streaming/)

## Store

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

### 1. Migrating S3 to Object Storage

Object storage powers files that matter to users and business operations: images, documents, static assets, media files, uploads, and generated content. Azion Object Storage provides S3-compatible storage with zero data transfer out cost.

#### Key Differences

| Aspect | Amazon S3 | Azion Object Storage |
| :----- | :-------- | :------------------- |
| **Endpoint** | `https://s3.amazonaws.com/bucket` | `https://s3.us-east-005.azionstorage.net` |
| **S3 endpoint** | `s3.amazonaws.com` | `s3.us-east-005.azionstorage.net` |
| **Region** | Multiple regions | `us-east-005` |
| **Data transfer out** | Charged per GB | Zero cost |
| **Storage class** | Standard, Intelligent-Tiering, Glacier | Standard |
| **Bucket limits** | 100 per account (default) | 100 per account (default) |

#### Update Configuration

Update your S3 client configuration to use Azion Object Storage:

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

// Before: AWS S3
const s3Client = new S3Client({
  region: 'us-east-1',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
  }
});

// After: Azion Object Storage
const s3Client = 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')
  }
});
`} />

#### Create S3 Credentials

<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 **Object Storage**.
3. Navigate to **S3 Credentials** tab.
4. Click **+ Credential**.
5. Select the bucket or account scope.
6. Configure capabilities (read, write, delete, list).
7. Save the access key and secret key securely.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create S3 credentials
curl -X POST 'https://api.azionapi.net/v4/workspace/storage/s3_credentials' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "bucket": "my-bucket",
    "capabilities": ["readFiles", "writeFiles", "deleteFiles", "listFiles"]
  }'
`} />
:::note
S3 credentials are created via the `/v4/workspace/storage/s3_credentials` endpoint. The `capabilities` field defines which operations the credential can perform. Save the returned `secret_key` immediately as it cannot be retrieved later.
:::
</Fragment>
</Tabs>

#### 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 Amazon S3 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://aws-bucket/ s3://azion-bucket/` | Syncs between buckets. |

#### Migrate Data with AWS CLI

Configure AWS CLI with Azion credentials:

<Code lang="bash" code={`
# Configure AWS CLI profile for Azion
aws configure --profile azion
# Access Key: [your Azion access key]
# Secret Key: [your Azion secret key]
# Region: us-east-005

# List buckets
aws s3 ls --profile azion --endpoint-url https://s3.us-east-005.azionstorage.net

# Sync from AWS S3 to Azion
aws s3 sync s3://source-bucket/ s3://dest-bucket/ \\
  --profile azion \\
  --endpoint-url https://s3.us-east-005.azionstorage.net
`} />

#### Migrate Data with rclone

[rclone](https://rclone.org) supports syncing between different storage providers:

<Code lang="bash" code={`
# Configure rclone for AWS S3 (source)
rclone config
# Name: aws-s3
# Storage: s3
# Provider: AWS
# env_auth: true

# Configure rclone for Azion (destination)
rclone config
# Name: azion
# Storage: s3
# Provider: Other
# endpoint: https://s3.us-east-005.azionstorage.net
# acl: private

# Sync from AWS to Azion
rclone sync aws-s3:source-bucket azion:dest-bucket --progress
`} />

:::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.
:::

#### Use Bucket as Origin

Configure Object Storage as an origin for your Application:

<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 **Connectors**.
3. Create a new Connector with type **Object Storage**.
4. Select your bucket.
5. Configure the prefix (optional).
6. Associate the Connector with your Application.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a Connector using Object Storage as origin
curl -X POST 'https://api.azionapi.net/v4/workspace/connectors' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "My Object Storage Origin",
    "type": "object_storage",
    "attributes": {
      "bucket": "my-bucket",
      "prefix": "assets/"
    }
  }'
`} />
:::note
Connectors are created via `/v4/workspace/connectors`. Use `type: "object_storage"` and specify the bucket name. The optional `prefix` field limits objects served to a specific path within the bucket.
:::
</Fragment>
</Tabs>

#### 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/)

### 2. Migrating DynamoDB to KV Store / SQL Database

DynamoDB is a serverless key-value and document database. The migration destination depends on your use case: key-value operations map to KV Store, while complex queries map to SQL Database.

#### Key Differences

| Aspect | Amazon DynamoDB | Azion KV Store | Azion SQL Database |
| :----- | :-------------- | :------------- | :----------------- |
| **Data model** | Key-value, document | Key-value | Relational (SQLite) |
| **Query capability** | Key lookups, queries, scans | Key lookups, hash operations | Full SQL |
| **Global replication** | Global Tables (multi-Region) | Global by default | Main/Replicas architecture |
| **Consistency** | Eventually consistent, strong | Eventual | Strong (ACID) |
| **Indexing** | GSI, LSI | Not supported | Full SQL indexing |
| **Capacity mode** | On-demand, provisioned | Serverless | Serverless |

#### Migration Decision Guide

| DynamoDB Feature | Recommended Azion Service |
| :--------------- | :------------------------ |
| Primary key lookups | KV Store |
| Simple key-value operations | KV Store |
| Session storage | KV Store |
| Feature flags, configuration | KV Store |
| Complex queries with filters | SQL Database |
| Secondary index queries | SQL Database |
| Aggregations, joins | SQL Database |
| Relational data model | SQL Database |

#### Migrate to KV Store

For key-value workloads, use KV Store with a Redis-like API:

<Code lang="javascript" code={`
import { createClient } from 'azion/kv';

// Create KV client
const client = await createClient({
  namespace: 'my-namespace'
})
  .on('error', (err) => console.error('KV Error:', err))
  .connect();

// Before: DynamoDB GetItem
// const result = await dynamodb.getItem({
//   TableName: 'Users',
//   Key: { userId: { S: '123' } }
// }).promise();

// After: KV Store get
const userData = await client.get('user:123');

// Before: DynamoDB PutItem
// await dynamodb.putItem({
//   TableName: 'Users',
//   Item: { userId: { S: '123' }, name: { S: 'John' } }
// }).promise();

// After: KV Store set
await client.set('user:123', JSON.stringify({ name: 'John' }), {
  expiration: { type: 'EX', value: 3600 } // 1 hour TTL
});
`} />

#### Create a KV Store

<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 **KV Store**.
3. Click **+ Store**.
4. Enter a name for your store.
5. Configure settings.
6. Click **Save**.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a KV Store
curl -X POST 'https://api.azionapi.net/v4/workspace/kv/namespaces' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "my-kv-store",
    "description": "Migrated from DynamoDB"
  }'
`} />
:::note
KV Store namespaces are created via `/v4/workspace/kv/namespaces`. Use the namespace name in your Functions to interact with the store.
:::
</Fragment>
</Tabs>

#### Migrate to SQL Database

For complex query workloads, migrate to SQL Database:

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

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

// Before: DynamoDB Query with filter
// const result = await dynamodb.query({
//   TableName: 'Orders',
//   IndexName: 'CustomerIdIndex',
//   KeyConditionExpression: 'customerId = :cid',
//   FilterExpression: 'orderDate > :date'
// }).promise();

// After: SQL Database query
const orders = await db.query(
  'SELECT * FROM orders WHERE customer_id = ? AND order_date > ?',
  ['customer-123', '2024-01-01']
);

// Iterate results
let row = await orders.next();
while (row) {
  console.log(row.getString(0)); // access column by index
  row = await orders.next();
}
`} />

#### Create a SQL Database

<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 **SQL Database**.
3. Click **+ Database**.
4. Enter a name for your database.
5. Create tables using SQL Shell or API.
6. Import your data.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a SQL Database
curl -X POST 'https://api.azionapi.net/v4/workspace/sql/databases' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "my-database",
    "description": "Migrated from DynamoDB"
  }'
`} />
:::note
SQL Database instances are created via `/v4/workspace/sql/databases`. Use SQL Shell or the API to create tables and import data.
:::
</Fragment>
</Tabs>

#### Export DynamoDB Data

Export DynamoDB data and transform for import:

<Code lang="bash" code={`
# Export DynamoDB table to S3
aws dynamodb export-table-to-point-in-time \\
  --table-name Users \\
  --s3-bucket my-export-bucket \\
  --export-format DYNAMODB_JSON

# Convert and import to Azion
# For KV Store: Transform to key-value pairs
# For SQL Database: Transform to SQL INSERT statements
`} />

#### Global Tables Migration

DynamoDB Global Tables provide multi-Region replication. KV Store is global by default:

| DynamoDB Global Tables | Azion KV Store |
| :--------------------- | :------------- |
| Multi-Region replication | Global by default |
| Conflict resolution: Last writer wins | Automatic synchronization |
| Eventual consistency | Low-latency global access |
| Additional cost per replicated write | No additional replication cost |

#### Reference documentation

* [KV Store](https://www.azion.com/en/documentation/products/store/kv-store/)
* [KV library (azion/kv)](https://www.azion.com/en/documentation/products/azion-lib/kv/)
* [SQL Database](https://www.azion.com/en/documentation/products/store/sql-database/)
* [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/)
* [Import data into SQL Database](https://www.azion.com/en/documentation/products/guides/import-data-sql-database/)

### 3. Migrating RDS/Aurora to SQL Database

Relational database migration moves your transactional data and SQL workloads to Azion SQL Database. Azion SQL Database is SQLite-compatible and provides ACID compliance with a distributed Main/Replicas architecture.

#### Key Differences

| Aspect | Amazon RDS/Aurora | Azion SQL Database |
| :----- | :---------------- | :----------------- |
| **Engine** | MySQL, PostgreSQL, MariaDB, Oracle, SQL Server | SQLite |
| **Compatibility** | Engine-specific | PostgreSQL-compatible API |
| **Architecture** | Primary/Replicas | Main/Replicas (distributed) |
| **Connection** | Connection string, connection pooling | Runtime API (no connection pooling needed) |
| **Transactions** | ACID | ACID |
| **Scaling** | Vertical scaling, read replicas | Distributed architecture |
| **Region** | Single or multi-Region | Global Network |

#### PostgreSQL to SQL Database Migration

For PostgreSQL workloads, Azion SQL Database provides a familiar SQL interface:

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

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

// Before: PostgreSQL query
// const result = await pgClient.query(
//   'SELECT id, name, email FROM users WHERE status = $1',
//   ['active']
// );

// After: SQL Database query
const result = await db.query(
  'SELECT id, name, email FROM users WHERE status = ?',
  ['active']
);

// Process results
let row = await result.next();
while (row) {
  const id = row.getString(0);
  const name = row.getString(1);
  const email = row.getString(2);
  console.log(\`User: \${name} <\${email}>\`);
  row = await result.next();
}
`} />

#### Create a SQL Database

<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 **SQL Database**.
3. Click **+ Database**.
4. Enter a name for your database.
5. Click **Save**.
6. Use **SQL Shell** to create tables and import data.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
# Create a SQL Database
curl -X POST 'https://api.azionapi.net/v4/workspace/sql/databases' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "production-db",
    "description": "Migrated from Aurora PostgreSQL"
  }'

# Execute SQL to create tables
curl -X POST 'https://api.azionapi.net/v4/workspace/sql/databases/{database_id}/query' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "query": "CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT, email TEXT, created_at TIMESTAMP)"
  }'
`} />
:::note
SQL Database instances are created via `/v4/workspace/sql/databases`. Use the query endpoint to execute DDL statements for table creation.
:::
</Fragment>
</Tabs>

#### Export and Import Data

Export data from RDS/Aurora and import to SQL Database:

<Code lang="bash" code={`
# Export from RDS PostgreSQL
pg_dump -h my-db.xxxx.region.rds.amazonaws.com \\
  -U admin \\
  -d mydb \\
  --data-only \\
  --inserts \\
  > export.sql

# For Aurora, you can also use Snapshot Export to S3
aws rds start-export-task \\
  --export-task-identifier my-export \\
  --source-arn arn:aws:rds:region:account:cluster:my-aurora-cluster \\
  --s3-bucket-name my-export-bucket \\
  --export-only data

# Import to Azion SQL Database via SQL Shell
# Connect to SQL Shell and run the export.sql file
# Or use the import API
`} />

#### Data Type Mapping

| PostgreSQL Type | SQLite Equivalent |
| :-------------- | :---------------- |
| INTEGER, BIGINT, SMALLINT | INTEGER |
| SERIAL, BIGSERIAL | INTEGER (auto-increment) |
| VARCHAR(n), CHAR(n), TEXT | TEXT |
| BOOLEAN | INTEGER (0 or 1) |
| REAL, DOUBLE PRECISION | REAL |
| DECIMAL, NUMERIC | REAL |
| DATE, TIME, TIMESTAMP | TEXT (ISO 8601 format) |
| JSON, JSONB | TEXT (use JSON functions) |
| UUID | TEXT |
| BYTEA | BLOB |

#### 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/)
* [SQL Database API reference](https://www.azion.com/en/documentation/runtime/api-reference/sql-database/)

### 4. Migrating ElastiCache to Cache / KV Store

ElastiCache provides in-memory caching with Redis or Memcached. Azion provides caching through Cache and key-value storage through KV Store.

#### Key Differences

| Aspect | Amazon ElastiCache | Azion Cache | Azion KV Store |
| :----- | :---------------- | :---------- | :------------- |
| **Type** | In-memory cache | Cache | Distributed key-value |
| **Engines** | Redis, Memcached | HTTP cache | Redis-like API |
| **Persistence** | Optional (Redis AOF/RDB) | Time-based TTL | Persistent |
| **Data structures** | Strings, hashes, lists, sets, sorted sets | HTTP responses | Strings, hashes |
| **Replication** | Cluster mode, replication groups | Global Network | Global by default |
| **Access** | TCP connection | HTTP request/response | Runtime API |

#### Migration Decision Guide

| ElastiCache Use Case | Recommended Azion Service |
| :------------------- | :------------------------ |
| HTTP response caching | Cache |
| Session storage | KV Store |
| Rate limiting counters | KV Store |
| Feature flags | KV Store |
| Database query caching | Cache + Functions |
| Pub/Sub messaging | Functions + KV Store |
| Leaderboards, sorted sets | SQL Database |
| Complex data structures | SQL Database |

#### Migrate Redis Caching to KV Store

For Redis-like key-value operations, use KV Store:

<Code lang="javascript" code={`
import { createClient } from 'azion/kv';

// Create KV client with Redis-like API
const client = await createClient()
  .on('error', (err) => console.error('KV Error:', err))
  .connect();

// Before: Redis SET with expiration
// await redis.set('session:abc123', JSON.stringify(sessionData), 'EX', 3600);

// After: KV Store set with expiration
await client.set('session:abc123', JSON.stringify(sessionData), {
  expiration: { type: 'EX', value: 3600 }
});

// Before: Redis GET
// const data = await redis.get('session:abc123');

// After: KV Store get
const data = await client.get('session:abc123');

// Before: Redis DEL
// await redis.del('session:abc123');

// After: KV Store delete
await client.delete('session:abc123');
`} />

#### Reference documentation

* [KV Store](https://www.azion.com/en/documentation/products/store/kv-store/)
* [KV library (azion/kv)](https://www.azion.com/en/documentation/products/azion-lib/kv/)
* [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/)
* [Rules Engine for Applications](https://www.azion.com/en/documentation/products/build/applications/rules-engine/)

## Observe 

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

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

CloudWatch Metrics provides monitoring for AWS resources and applications. Azion Real-Time Metrics delivers comparable capabilities through a GraphQL API and integrated dashboards with near real-time data aggregation.

#### Key Differences

| Aspect | Amazon CloudWatch Metrics | Azion Real-Time Metrics |
| :----- | :------------------------ | :---------------------- |
| **Data freshness** | Near real-time (1-5 minutes) | Near real-time (up to 10 minutes) |
| **Retention** | 15 months (standard) | 2 years |
| **Query method** | GetMetricStatistics API, CloudWatch Insights | GraphQL API, Console dashboards |
| **Metrics** | Custom metrics, namespace-based | Request, bandwidth, latency, cache, WAF, DNS |
| **Granularity** | 1 second to 1 day | Adaptive intervals (minute/hour/day) |
| **Dashboards** | CloudWatch Dashboards | Real-Time Metrics + Grafana plugin |
| **Alarms** | CloudWatch Alarms | External monitoring via Data Stream |

#### Available Metrics

Azion Real-Time Metrics provides comprehensive monitoring across product categories:

**Build metrics:**
- **Applications**: Total requests, data transferred, status codes, bandwidth saving, average request time
- **Functions**: Total invocations, execution time
- **Image Processor**: Total requests, requests per second
- **Tiered Cache**: Caching offload, L2 offload

**Secure metrics:**
- **WAF**: Threats vs requests, SQL injection, XSS, RFI, threats by country
- **Edge DNS**: Total queries
- **Bot Manager**: Bot hits, bad bot hits, good bot hits, traffic classification

**Observe metrics:**
- **Data Stream**: Total data streamed, total requests

#### Configuration Steps

<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 a category tab (Build, Secure, Observe).
4. Select a product tab to view specific metrics.
5. Configure **Time range** (Last Hour, 24 Hours, 7 Days, 30 Days, 6 Months).
6. Use **Filters** to refine analysis by host, status code, or other dimensions.
7. Click the context menu on any chart to export CSV or copy the GraphQL query.
</Fragment>

<Fragment slot="panel.api">
<Code lang="graphql" code={`
query HttpMetrics {
  http(
    filter: { tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-02T00:00:00" } }
    aggregate: { sum: requests }
    groupBy: [ts]
    orderBy: [ts_DESC]
    first: 100
  ) {
    ts
    sum
  }
}
`} />
:::note
Real-Time Metrics uses the GraphQL API at `https://console.azion.com/metrics/graphql`. Queries support filtering by time range, aggregation functions (sum, avg), grouping, and ordering. The API returns up to 10,000 lines per query.
:::
</Fragment>
</Tabs>

#### GraphQL Query Examples

**Query requests by status code:**

<Code lang="graphql" code={`
query RequestsByStatus {
  http(
    filter: {
      tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-01T23:59:59" }
    }
    aggregate: { sum: requests }
    groupBy: [status]
    orderBy: [sum_DESC]
    first: 20
  ) {
    status
    sum
  }
}
`} />

**Query WAF threats by country:**

<Code lang="graphql" code={`
query WafThreatsByCountry {
  waf(
    filter: {
      tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-02T00:00:00" }
    }
    aggregate: { sum: threats }
    groupBy: [country]
    orderBy: [sum_DESC]
    first: 10
  ) {
    country
    sum
  }
}
`} />

**Query data transferred for specific host:**

<Code lang="graphql" code={`
query DataTransferredByHost {
  http(
    filter: {
      tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-07T00:00:00" }
      host: { eq: "www.example.com" }
    }
    aggregate: { sum: dataTransferred }
    groupBy: [ts]
    first: 500
  ) {
    ts
    sum
  }
}
`} />

#### CloudWatch Alarm Migration

CloudWatch Alarms notify on metric thresholds. Azion doesn't provide built-in alerting, but you can achieve similar functionality:

| CloudWatch Alarm | Azion Equivalent |
| :--------------- | :--------------- |
| Metric threshold alarm | Configure alerts in external monitoring (Datadog, Splunk) via Data Stream |
| Composite alarms | Functions with custom logic + Data Stream |
| Anomaly detection | External SIEM/analytics platforms |

#### Grafana Integration

Use the Azion Grafana plugin for custom dashboards:

<Code lang="bash" code={`
# Install Azion Grafana plugin
grafana-cli plugins install aziontech-azion-plugin
`} />

Reference the [Grafana plugin documentation](https://github.com/aziontech/grafana-plugin) for dashboard configuration.

#### 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/)

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

CloudWatch Logs collects and stores log data from AWS resources. Azion Real-Time Events provides immediate log access through Console or GraphQL API for real-time troubleshooting and investigation.

#### Key Differences

| Aspect | Amazon CloudWatch Logs | Azion Real-Time Events |
| :----- | :--------------------- | :--------------------- |
| **Access method** | GetLogEvents API, CloudWatch Logs Insights | Real-time query via Console or GraphQL API |
| **Latency** | Seconds to minutes | Seconds |
| **Retention** | 1 day to 10 years (configurable) | 7 days (168 hours), 2 years for Activity History |
| **Query language** | CloudWatch Logs Insights (SQL-like) | GraphQL queries |
| **Log groups** | Log groups with log streams | Data sources by product type |
| **Metric filters** | Create metrics from logs | Use Data Stream for custom processing |

#### Data Sources Mapping

| CloudWatch Log Group | Azion Real-Time Events Data Source |
| :------------------- | :--------------------------------- |
| /aws/cloudfront/... | HTTP Requests |
| /aws/lambda/... | Functions |
| /aws/waf/... | HTTP Requests (WAF fields) |
| /aws/route53/... | Edge DNS |
| CloudTrail | Activity History |

#### Configuration Steps

<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 **Data Source** tab (HTTP Requests, Functions, Edge DNS, etc.).
4. Configure **Time filter** (Last 15 minutes to Last 7 days, or Custom time range).
5. Add filters to narrow results (host, status, remote address, etc.).
6. Click **Search** to query logs.
7. Click any row to see detailed log information in **More details** view.
</Fragment>

<Fragment slot="panel.api">
<Code lang="graphql" code={`
query HttpEvents {
  http(
    filter: {
      tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-01T01:00:00" }
      status: { eq: "500" }
    }
    orderBy: [ts_DESC]
    first: 100
  ) {
    ts
    remoteAddress
    requestUri
    status
    upstreamResponseTime
    host
    requestMethod
  }
}
`} />
:::note
Real-Time Events GraphQL API queries data from the last 168 hours (7 days). For Activity History, queries can span up to 2 years. The API supports filtering, ordering, and pagination with cursor-based navigation.
:::
</Fragment>
</Tabs>

#### CloudWatch Logs Insights to GraphQL Migration

Convert CloudWatch Logs Insights queries to Real-Time Events GraphQL:

**CloudWatch Logs Insights query:**
<Code lang="text" code={`
fields @timestamp, @message
| filter @logGroup = "/aws/cloudfront/distribution"
| filter status >= 500
| sort @timestamp desc
| limit 100
`} />

**Azion GraphQL equivalent:**
<Code lang="graphql" code={`
query ErrorRequests {
  http(
    filter: {
      tsRange: { begin: "2024-01-01T00:00:00", end: "2024-01-01T23:59:59" }
      status: { gte: "500" }
    }
    orderBy: [ts_DESC]
    first: 100
  ) {
    ts
    status
    requestUri
    host
    remoteAddress
    upstreamStatus
    upstreamResponseTime
  }
}
`} />

#### Available Variables by Data Source

**HTTP Requests:**
- Request metadata: `ts`, `remoteAddress`, `remotePort`, `host`, `requestUri`, `requestMethod`, `status`
- Performance: `requestTime`, `upstreamResponseTime`, `upstreamHeaderTime`
- Bandwidth: `bytesSent`, `requestLength`, `upstreamBytesReceived`, `upstreamBytesSent`
- Cache: `upstreamCacheStatus`
- Security: `wafBlock`, `wafMatch`, `wafScore`, `wafLearning`
- Geo: `geoipCountryName`, `geoipRegionName`, `geoipAsn`
- TLS: `sslCipher`, `sslProtocol`

**Functions:**
- `functionId`, `functionsList`, `functionsTime`, `functionLanguage`

**Edge DNS:**
- `level`, `qType`, `resolutionType`, `statusCode`, `zoneId`

#### Log-Based Metrics

To create metrics from logs (equivalent to CloudWatch metric filters), use 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. Select **Applications** as data source.
5. Use **Custom Template** to select specific variables.
6. Choose an endpoint (Datadog, Splunk, Elasticsearch, etc.).
7. Configure the destination for log processing.
8. Activate the stream.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
curl -X POST 'https://api.azion.com/v4/workspace/stream/streams' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "Log Metrics Stream",
    "source": {
      "type": "applications"
    },
    "template_id": 12345,
    "endpoint": {
      "type": "datadog",
      "name": "my-datadog-endpoint",
      "url": "https://http-intake.logs.datadoghq.com/v1/input",
      "api_key": "YOUR_DATADOG_API_KEY"
    },
    "active": true
  }'
`} />
</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 X-Ray to Data Stream

AWS X-Ray provides distributed tracing and request tracing across services. Azion Data Stream enables streaming of observability data to external destinations for distributed tracing analysis.

#### Key Differences

| Aspect | AWS X-Ray | Azion Data Stream |
| :----- | :-------- | :---------------- |
| **Trace collection** | Automatic with X-Ray SDK | Stream logs to external tracing systems |
| **Service map** | Built-in service map visualization | External tools (Datadog, Jaeger, Splunk) |
| **Trace analysis** | X-Ray console | External tracing platforms |
| **Annotations** | Custom key-value pairs | Custom log templates |
| **Sampling** | Configurable sampling rules | Configurable sampling percentage |
| **Destinations** | X-Ray console, CloudWatch | 10+ external destinations |

#### Tracing Data Flow Migration

| AWS X-Ray Concept | Azion Equivalent |
| :---------------- | :--------------- |
| Segments | Request/response log entries |
| Subsegments | Functions execution logs |
| Service graph | Built in external tracing tools (Datadog, Jaeger) |
| Trace ID propagation | Custom headers via Rules Engine or Functions |
| Annotations | Log variables in Data Stream template |

#### 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** > **Data Stream**.
3. Click **+ Stream**.
4. Select **Applications** as data source for request tracing.
5. Select **Functions** as additional data source for function execution traces.
6. Create a **Custom Template** with trace-related variables:
   - `$request_id` (unique trace identifier)
   - `$ts` (timestamp)
   - `$upstream_addr` (origin address)
   - `$upstream_response_time` (response time)
   - `$request_uri`, `$status`, `$host`
7. Choose a tracing-compatible endpoint (Datadog, Splunk, Elasticsearch, Kafka).
8. Configure destination credentials.
9. Activate the stream.
</Fragment>

<Fragment slot="panel.api">
<Code lang="bash" code={`
curl -X POST 'https://api.azion.com/v4/workspace/stream/streams' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "Distributed Tracing Stream",
    "source": {
      "type": "applications"
    },
    "template": {
      "name": "Custom Trace Template",
      "variables": [
        "$request_id",
        "$ts",
        "$host",
        "$request_uri",
        "$request_method",
        "$status",
        "$upstream_addr",
        "$upstream_response_time",
        "$upstream_status",
        "$remote_addr"
      ]
    },
    "endpoint": {
      "type": "datadog",
      "name": "tracing-endpoint",
      "url": "https://http-intake.logs.datadoghq.com/v1/input",
      "api_key": "YOUR_DATADOG_API_KEY"
    },
    "active": true
  }'
`} />
:::note
Data Stream uses `/v4/workspace/stream/streams` endpoint. Configure custom templates with trace-relevant variables. The `$request_id` field provides a unique identifier for correlating requests across services.
:::
</Fragment>
</Tabs>

#### Trace ID Propagation

To enable distributed tracing across services, propagate trace context via HTTP headers:

**Using Rules Engine:**

<Code lang="text" code={`
Criteria: All requests
Behavior: Add Request Header
Header Name: X-Trace-Id
Header Value: \${request_id}
`} />

**Using Functions:**

<Code lang="javascript" code={`
export default {
  async fetch(request) {
    // Extract or generate trace ID
    const traceId = request.headers.get('x-trace-id') ||
                    crypto.randomUUID();

    // Add trace ID to upstream request
    const upstreamRequest = new Request(request, {
      headers: {
        ...Object.fromEntries(request.headers),
        'X-Trace-Id': traceId
      }
    });

    return fetch(upstreamRequest);
  }
};
`} />

#### Supported Endpoints for Tracing

Data Stream supports multiple endpoints suitable for distributed tracing:

| Endpoint | Use Case |
| :------- | :------- |
| **Datadog** | Full APM and distributed tracing |
| **Splunk** | Log analytics and tracing |
| **Elasticsearch** | Search and trace correlation |
| **Apache Kafka** | Stream to Jaeger, Zipkin, or custom tracing |
| **Google BigQuery** | Data warehouse for trace analysis |
| **AWS Kinesis Data Firehose** | Integration with AWS X-Ray or other AWS services |
| **Standard HTTP/HTTPS POST** | Custom tracing systems |

#### Data Firehose Migration

AWS Kinesis Data Firehose delivers streaming data to destinations. Azion Data Stream provides similar capabilities:

| AWS Kinesis Data Firehose | Azion Data Stream |
| :------------------------ | :---------------- |
| S3 destination | S3 endpoint (any S3-compatible storage) |
| Redshift destination | BigQuery or custom HTTP endpoint |
| Elasticsearch destination | Elasticsearch endpoint |
| HTTP endpoint | Standard HTTP/HTTPS POST |
| Data transformation (Lambda) | Functions for preprocessing |

**Configure Data Stream for S3:**

<Code lang="bash" code={`
curl -X POST 'https://api.azion.com/v4/workspace/stream/streams' \\
  --header 'Authorization: Token YOUR_TOKEN' \\
  --header 'Content-Type: application/json' \\
  --data '{
    "name": "S3 Archive Stream",
    "source": {
      "type": "applications"
    },
    "template_id": 12345,
    "endpoint": {
      "type": "s3",
      "name": "my-s3-endpoint",
      "host_url": "https://s3.amazonaws.com",
      "bucket_name": "my-logs-bucket",
      "region": "us-east-1",
      "access_key": "YOUR_ACCESS_KEY",
      "secret_key": "YOUR_SECRET_KEY",
      "object_key_prefix": "azion-logs"
    },
    "active": true
  }'
`} />

#### CloudWatch RUM to Edge Pulse

CloudWatch RUM provides real user monitoring. Azion Edge Pulse delivers comparable capabilities:

| Aspect | CloudWatch RUM | Azion Edge Pulse |
| :----- | :------------- | :--------------- |
| **Data collection** | JavaScript SDK | JavaScript SDK |
| **Metrics** | Page load, Core Web Vitals, JavaScript errors | Real user metrics, performance data |
| **Session replay** | Available | Available via integration |
| **Custom events** | Custom events API | Custom events via SDK |

Configure Edge Pulse for real user monitoring:

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

<Fragment slot="panel.console">
1. Access [Azion Console](https://console.azion.com/).
2. Go to **Products menu** > **Edge Pulse**.
3. Create a new Pulse instance.
4. Configure the JavaScript snippet for your application.
5. Add the snippet to your application's HTML.
6. Configure data collection settings.
7. View metrics in Real-Time Metrics under Edge Pulse.
</Fragment>
</Tabs>

#### 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/)
* [Edge Pulse](https://www.azion.com/en/documentation/products/observe/edge-pulse/)

## Troubleshooting

| Problem | Likely Cause | Solution |
| :------ | :----------- | :------- |
| DNS not resolving | Nameserver propagation delay | Wait up to 48 hours after updating nameservers; verify with `dig yourdomain.com NS` |
| Certificate validation fails | Domain ownership not verified | Confirm DNS TXT record or HTTP challenge is accessible; check Certificate Manager status |
| Function returns `process.env not defined` | Node.js environment variable syntax used | Use `Azion.env.get('VARIABLE_NAME')` instead of `process.env.VARIABLE_NAME` |
| Cache not purging as expected | Purge request still processing | Wait 5-10 minutes; verify purge via `curl -I` to check headers; use wildcard purge for broad changes |
| WAF rules blocking legitimate traffic | Sensitivity too high or false positive | Switch WAF to Learning mode first; review blocked requests in Real-Time Events; adjust sensitivity |
| Origin connection timeouts | Connector misconfiguration or origin unavailable | Verify Connector address and port; check origin health; increase timeout in Connector settings |
| SSL handshake failures | Certificate mismatch or incomplete chain | Verify certificate covers the domain; include intermediate CA in certificate chain; check TLS minimum version |
| CORS errors on API requests | Missing CORS headers in response | Add CORS headers via Rules Engine: `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods` |
| Lambda function signature errors | CloudFront event structure differs from Azion | Update function to use `fetch(request, env, ctx)` signature; access request via `request` object |
| DynamoDB queries fail after migration | KV Store API syntax differs | Update code to use `KVStore` from `azion:kv`; check key naming conventions |
| S3 uploads fail with 403 | Incorrect credentials or endpoint | Verify Access Key and Secret Key; confirm endpoint is `s3.us-east-005.azionstorage.net` |
| CloudWatch metrics not appearing | Data Stream not configured | Set up Data Stream to export metrics; verify destination credentials and format |

## Key Advantages After Migration

| Capability | Before (AWS) | After (Azion) |
| :--------- | :----------- | :------------ |
| **Unified platform** | Multiple consoles for CloudFront, Lambda, S3, Route 53, WAF, CloudWatch | Single console for compute, storage, security, and observability |
| **Cold starts** | Possible on Lambda (especially with VPC) | Minimized with distributed V8 isolates |
| **Global distribution** | Regions and edge locations (200+ PoPs) | Azion platform locations worldwide with consistent performance |
| **Pricing model** | Per-service billing, data transfer fees, request counts | Simpler consolidated billing; zero DTO cost for Object Storage |
| **Observability** | CloudWatch with separate dashboards, logs, and alarms | Real-Time Metrics and Events with instant access via Console or GraphQL API |
| **Security integration** | WAF, Shield, IAM as separate services | Built-in WAF, DDoS Protection, Bot Manager integrated with workloads |

## 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
* Set up [Data Stream](https://www.azion.com/en/documentation/products/observe/data-stream/) to export logs to your existing SIEM or analytics tools

### 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 CloudFront distribution, a few Lambda functions, an S3 bucket, maybe a DynamoDB table. 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 cache behaviors. 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.