From 559e14472b6bbcd2174a87ed8b06b31dca624594 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 11:28:09 +0530 Subject: [PATCH 1/6] Refactor VM deployment documentation --- .../deploy-operate/deploy/aws-azure-gcp.md | 2 +- .../deploy/graalvm-native-images.md | 2 +- en/docs/deploy/overview.md | 2 +- ...-and-vm-deployment.md => vm-deployment.md} | 102 ++++++++---------- .../understand-ide/views/integration-view.md | 2 +- .../understand-ide/views/project-view.md | 2 +- .../project/ballerinatoml-reference.md | 2 +- en/sidebars.ts | 2 +- 8 files changed, 49 insertions(+), 67 deletions(-) rename en/docs/deploy/self-hosted/{local-and-vm-deployment.md => vm-deployment.md} (86%) diff --git a/en/docs/deploy-operate/deploy/aws-azure-gcp.md b/en/docs/deploy-operate/deploy/aws-azure-gcp.md index 571656a1c3..65ec23913d 100644 --- a/en/docs/deploy-operate/deploy/aws-azure-gcp.md +++ b/en/docs/deploy-operate/deploy/aws-azure-gcp.md @@ -279,5 +279,5 @@ For non-Kubernetes environments (ECS, VM-based), use cloud-native service discov ## What's next -- [Local and VM deployment](../../deploy/self-hosted/local-and-vm-deployment.md) -- Develop and test before deploying +- [VM Deployment](../../deploy/self-hosted/vm-deployment.md) -- Develop and test before deploying - [Scaling & High Availability](scaling-high-availability.md) -- Configure scaling and resilience diff --git a/en/docs/deploy-operate/deploy/graalvm-native-images.md b/en/docs/deploy-operate/deploy/graalvm-native-images.md index abb8d85efd..e59979c05c 100644 --- a/en/docs/deploy-operate/deploy/graalvm-native-images.md +++ b/en/docs/deploy-operate/deploy/graalvm-native-images.md @@ -194,5 +194,5 @@ Deploy the generated ZIP -- cold start drops from seconds to under 100ms. ## What's next - [Serverless Deployment](serverless-deployment.md) -- Deploy native images as Lambda functions -- [Local and VM deployment](../../deploy/self-hosted/local-and-vm-deployment.md) -- Run native binaries on virtual machines +- [VM Deployment](../../deploy/self-hosted/vm-deployment.md) -- Run native binaries on virtual machines - [Containerized Deployment](../../deploy/self-hosted/containerized-deployment.md) -- Build minimal container images for Docker, Kubernetes, and OpenShift diff --git a/en/docs/deploy/overview.md b/en/docs/deploy/overview.md index c9f5777b74..9184ff1e1e 100644 --- a/en/docs/deploy/overview.md +++ b/en/docs/deploy/overview.md @@ -14,7 +14,7 @@ Once your integration is ready, this section covers everything you need to ship WSO2 Integrator supports multiple deployment targets. Choose the one that fits your infrastructure: - **[WSO2 Cloud](./cloud/overview.md)** — Push your project directly from the IDE or the cloud editor to the managed WSO2 Integration Platform. No infrastructure setup required. -- **[Local and VM deployment](./self-hosted/local-and-vm-deployment.md)** — Run your integration on your local machine for development or testing, or deploy to a virtual machine or bare-metal server. +- **[VM Deployment](./self-hosted/vm-deployment.md)** — Deploy your integration to a virtual machine or bare-metal server as a standalone JAR file. - **[Containerized Deployment](./self-hosted/containerized-deployment.md)** — Package your integration as a container and deploy it to Docker, Kubernetes, or Red Hat OpenShift. - **[Serverless deployment](../deploy-operate/deploy/serverless-deployment.md)** — Run integrations as serverless functions. - **[AWS, Azure, and GCP](../deploy-operate/deploy/aws-azure-gcp.md)** — Deploy to major cloud providers using native services. diff --git a/en/docs/deploy/self-hosted/local-and-vm-deployment.md b/en/docs/deploy/self-hosted/vm-deployment.md similarity index 86% rename from en/docs/deploy/self-hosted/local-and-vm-deployment.md rename to en/docs/deploy/self-hosted/vm-deployment.md index 0b2289de31..8337f419d0 100644 --- a/en/docs/deploy/self-hosted/local-and-vm-deployment.md +++ b/en/docs/deploy/self-hosted/vm-deployment.md @@ -1,12 +1,12 @@ --- -title: Local and VM Deployment -description: Run WSO2 Integrator projects locally during development or deploy as standalone JAR files on virtual machines. -keywords: [wso2 integrator, bal run, run locally, vm deployment, jar deployment, ballerina cli] +title: VM Deployment +description: Deploy WSO2 Integrator projects as standalone JAR files on virtual machines for self-hosted production deployments. +keywords: [wso2 integrator, bal run, vm deployment, jar deployment, ballerina cli] --- -# Local and VM Deployment +# VM Deployment -This page explains how to run WSO2 Integrator projects either directly on your local machine during development using `bal run`, or as standalone JAR files on virtual machines for self-hosted production deployments. +This page explains how to run WSO2 Integrator projects as standalone JAR files on virtual machines for self-hosted production deployments. :::info Prerequisites - [Ballerina installed](https://ballerina.io/downloads/) on any machine where you want to run the project @@ -14,61 +14,6 @@ This page explains how to run WSO2 Integrator projects either directly on your l - For production VM deployments: Java Runtime (JDK 21 or later) ::: -## Run locally during development - -To run the project on your local machine during development: - -1. Open a terminal and navigate to the project directory. - - ```bash - cd my-integration - ``` - -2. Start the project. - - ```bash - bal run - ``` - -The Ballerina CLI compiles the project and starts the integration runtime. You will see the program output in the terminal. Integrations with listeners keep running until you terminate it by **`CTRL + C`** - -## Run on a VM from source - -To run the project on a remote virtual machine, install the Ballerina distribution on the VM and run the project directly from source using `bal run`. - -### Step 1: Push the project to a remote Git repository - -From your local machine, push the project to a remote Git repository such as GitHub, GitLab, or Bitbucket. - -```bash -git add . -git commit -m "Initial integration project" -git push origin main -``` - -### Step 2: Clone the repository on the VM - -SSH into the target VM and clone the repository. - -```bash -git clone https://github.com/your-org/my-integration.git -cd my-integration -``` - -### Step 3: Start the integration - -Run the project using the Ballerina CLI. - -```bash -bal run -``` - -The runtime starts and the integration begins serving traffic on the configured port. - -:::note -Ballerina must be installed on the VM. Download it from [ballerina.io](https://ballerina.io/downloads/). The version on the VM should match the version used during development. -::: - ## Deploy with executable JAR For production VM deployments, WSO2 Integrator projects compile to executable JAR files that run on any JVM. This approach gives you full control over the runtime environment and is ideal for traditional VM-based infrastructure. @@ -160,6 +105,43 @@ java \ curl http://localhost:9090/health ``` +## Run on a VM from source + +To run the project on a remote virtual machine, install the Ballerina distribution on the VM and run the project directly from source using `bal run`. + +### Step 1: Push the project to a remote Git repository + +From your local machine, push the project to a remote Git repository such as GitHub, GitLab, or Bitbucket. + +```bash +git add . +git commit -m "Initial integration project" +git push origin main +``` + +### Step 2: Clone the repository on the VM + +SSH into the target VM and clone the repository. + +```bash +git clone https://github.com/your-org/my-integration.git +cd my-integration +``` + +### Step 3: Start the integration + +Run the project using the Ballerina CLI. + +```bash +bal run +``` + +The runtime starts and the integration begins serving traffic on the configured port. + +:::note +Ballerina must be installed on the VM. Download it from [ballerina.io](https://ballerina.io/downloads/). The version on the VM should match the version used during development. +::: + ## Consolidated package deployment For organizations running multiple integrations, a consolidated deployment bundles several integration packages into a single runtime. diff --git a/en/docs/develop/understand-ide/views/integration-view.md b/en/docs/develop/understand-ide/views/integration-view.md index 1ed632777e..79a79a838f 100644 --- a/en/docs/develop/understand-ide/views/integration-view.md +++ b/en/docs/develop/understand-ide/views/integration-view.md @@ -76,7 +76,7 @@ The deployment options panel appears on the right sidebar and provides shortcuts |---|---| | [**Deploy to WSO2 Cloud**](../../../deploy/cloud/overview.md) | Fully managed cloud platform for hosting and running integrations. | | [**Containerized Deployment**](../../../deploy/self-hosted/containerized-deployment.md) | Build Docker images and deploy integrations to Docker, Kubernetes, or OpenShift. | -| [**Local and VM deployment**](../../../deploy/self-hosted/local-and-vm-deployment.md) | Run integrations locally during development or as standalone JAR files on virtual machines. | +| [**VM Deployment**](../../../deploy/self-hosted/vm-deployment.md) | Deploy integrations as standalone JAR files on virtual machines. | | [**Integration Control Plane (ICP)**](../../../deploy-operate/observe/integration-control-plane-icp.md) | Monitor and manage running integrations from a centralized dashboard. | Select **Enable ICP monitoring** to activate ICP for this integration, or expand **Publish to local ICP** to push the integration to a local Integration Control Plane instance. diff --git a/en/docs/develop/understand-ide/views/project-view.md b/en/docs/develop/understand-ide/views/project-view.md index cb0dbe7b94..5ffaca310c 100644 --- a/en/docs/develop/understand-ide/views/project-view.md +++ b/en/docs/develop/understand-ide/views/project-view.md @@ -44,7 +44,7 @@ The deployment options panel appears on the right sidebar and provides shortcuts |---|---| | [**Deploy to WSO2 Cloud**](../../../deploy/cloud/overview.md) | Fully managed cloud platform for hosting and running integrations. | | [**Containerized Deployment**](../../../deploy/self-hosted/containerized-deployment.md) | Build Docker images and deploy integrations to Docker, Kubernetes, or OpenShift. | -| [**Local and VM deployment**](../../../deploy/self-hosted/local-and-vm-deployment.md) | Run integrations locally during development or as standalone JAR files on virtual machines. | +| [**VM Deployment**](../../../deploy/self-hosted/vm-deployment.md) | Deploy integrations as standalone JAR files on virtual machines. | | [**Integration Control Plane (ICP)**](../../../deploy-operate/observe/integration-control-plane-icp.md) | Monitor and manage running integrations from a centralized dashboard. | At the project level, click **Enable ICP for all integrations** to activate ICP monitoring for every integration in the project at once. diff --git a/en/docs/reference/project/ballerinatoml-reference.md b/en/docs/reference/project/ballerinatoml-reference.md index 777413cd80..4cf091631f 100644 --- a/en/docs/reference/project/ballerinatoml-reference.md +++ b/en/docs/reference/project/ballerinatoml-reference.md @@ -229,6 +229,6 @@ options.mode = "client" ## What's next -- [Local and VM deployment](../../deploy/self-hosted/local-and-vm-deployment.md) — build and run the package you just configured. +- [VM Deployment](../../deploy/self-hosted/vm-deployment.md) — build and run the package you just configured. - [Cloud.toml reference](./cloudtoml-reference.md) — add Kubernetes and Docker deployment descriptors when you deploy. - [Configuration management](../config/configuration-management.md) — supply runtime values, override via environment variables, and target per-environment configuration. diff --git a/en/sidebars.ts b/en/sidebars.ts index 53b19933d7..4a1ec7a12c 100644 --- a/en/sidebars.ts +++ b/en/sidebars.ts @@ -1904,7 +1904,7 @@ const sidebars: SidebarsConfig = { type: 'category', label: 'Self-Hosted', items: [ - 'deploy/self-hosted/local-and-vm-deployment', + 'deploy/self-hosted/vm-deployment', 'deploy/self-hosted/containerized-deployment', 'deploy-operate/deploy/serverless-deployment', 'deploy-operate/deploy/aws-azure-gcp', From e119465a35aa8625a20f98b597e9a954a0062872 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 11:56:01 +0530 Subject: [PATCH 2/6] Update configuration management guide --- .../deploy/managing-configurations.md | 218 ++++++++++++++---- 1 file changed, 177 insertions(+), 41 deletions(-) diff --git a/en/docs/deploy-operate/deploy/managing-configurations.md b/en/docs/deploy-operate/deploy/managing-configurations.md index 7ece27141e..b623820e8b 100644 --- a/en/docs/deploy-operate/deploy/managing-configurations.md +++ b/en/docs/deploy-operate/deploy/managing-configurations.md @@ -14,9 +14,9 @@ Ballerina resolves configuration values from multiple sources, with the followin | Priority | Source | Example | |----------|--------|---------| -| 1 | Command-line arguments | `--myModule.port=9090` | -| 2 | Environment variables | `BAL_MY_MODULE_PORT=9090` | -| 3 | `Config.toml` file(s) | `[myModule] port = 9090` | +| 1 | Environment variables | `BAL_CONFIG_VAR_PORT=9090` | +| 2 | Command-line arguments | `-Cport=9090` | +| 3 | `Config.toml` file(s) or `BAL_CONFIG_DATA` | `port = 9090` | | 4 | Default values in code | `configurable int port = 8080;` | ## Defining configurable values @@ -90,37 +90,190 @@ level = "INFO" ### Selecting the config file at runtime -Use the `BAL_CONFIG_FILES` environment variable: +Use the `BAL_CONFIG_FILES` environment variable to specify one or more configuration files: +**Linux/macOS (colon-separated):** ```bash -# Use dev config -BAL_CONFIG_FILES=config/dev/Config.toml bal run +# Single config file +export BAL_CONFIG_FILES=config/prod/Config.toml +bal run -# Use production config -BAL_CONFIG_FILES=config/prod/Config.toml java -jar my_integration.jar +# Multiple config files (merged in order, later files override earlier) +export BAL_CONFIG_FILES=config/base/Config.toml:config/prod/Config.toml +java -jar my_integration.jar +``` + +**Windows (semicolon-separated):** +```cmd +REM Single config file +set BAL_CONFIG_FILES=config\prod\Config.toml +bal run + +REM Multiple config files +set BAL_CONFIG_FILES=config\base\Config.toml;config\prod\Config.toml +java -jar my_integration.jar +``` + +:::note +Once `BAL_CONFIG_FILES` is set, the default `Config.toml` in the current directory is ignored unless explicitly included in the path. +::: + +### Using BAL_CONFIG_DATA + +Provide TOML configuration directly as an environment variable: + +```bash +export BAL_CONFIG_DATA='port=9090 +dbHost="prod-db.example.com" +[logging] +level="INFO"' + +java -jar my_integration.jar ``` -Supply multiple config files (merged in order, later files override earlier): +This is useful in containerized environments where mounting config files is not convenient. + +## Command-line arguments + +Override specific configuration values using the `-C` flag: ```bash -BAL_CONFIG_FILES=config/base/Config.toml:config/prod/Config.toml java -jar my_integration.jar +# Single value +bal run -- -Cport=9090 + +# Multiple values +bal run -- -Cport=9090 -CdbHost=localhost -CdbName=orders + +# For JAR files +java -jar my_integration.jar -Cport=9090 -CdbPassword=secret ``` +Command-line arguments have higher priority than TOML files but lower priority than environment variables. + ## Environment variable overrides -Override any configurable value using environment variables. The naming convention is: +Override any configurable value using environment variables with the naming convention: + +``` +BAL_CONFIG_VAR_ +``` + +**Key rules:** +- All characters must be **UPPERCASE** +- Variable names from code are uppercased (e.g., `port` → `PORT`, `dbHost` → `DBHOST`) +- Underscores in variable names are preserved (e.g., `db_host` → `DB_HOST`) + +### Platform-specific syntax +**Linux/macOS:** +```bash +export BAL_CONFIG_VAR_PORT=9090 +bal run ``` -BAL__ (all uppercase, dots replaced with underscores) + +**Windows:** +```cmd +set BAL_CONFIG_VAR_PORT=9090 +bal run +``` + +### Examples by data type + +```ballerina +configurable int port = 8080; +configurable boolean isAdmin = false; +configurable float maxPayload = 1.0; +configurable string dbPassword = ?; ``` ```bash -export BAL_DB_HOST="prod-db.internal.example.com" -export BAL_DB_PASSWORD="s3cur3p@ss" +export BAL_CONFIG_VAR_PORT=9090 +export BAL_CONFIG_VAR_ISADMIN=true +export BAL_CONFIG_VAR_MAXPAYLOAD=2.5 +export BAL_CONFIG_VAR_DBPASSWORD="s3cur3p@ss" java -jar my_integration.jar ``` -This is useful for container orchestrators and CI/CD pipelines. +### Module-level configurables + +For configurables defined in separate modules, the environment variable includes the full module path. Given a project structure: + +``` +my_integration/ + ├── main.bal + └── modules/ + └── database/ + └── database.bal +``` + +If `modules/database/database.bal` contains: + +```ballerina +configurable string db_host = "localhost"; +configurable int db_port = 5432; +``` + +And your `Config.toml` organizes them as: + +```toml +[my_integration.database] +db_host = "prod-db.example.com" +db_port = 3306 +``` + +The environment variables are: + +```bash +export BAL_CONFIG_VAR_MY_INTEGRATION_DATABASE_DB_HOST="env-db.example.com" +export BAL_CONFIG_VAR_MY_INTEGRATION_DATABASE_DB_PORT=5432 +java -jar my_integration.jar +``` + +**Pattern:** `BAL_CONFIG_VAR___` with all dots converted to underscores and all characters uppercase. + +### Supported types and limitations + +:::note +**Supported types for environment variables:** +- Simple types: `int`, `byte`, `float`, `boolean`, `string`, `decimal`, `enum`, `xml` +- Values must be in the `toString()` representation of the type + +**Not supported:** +- Record types +- Array types +- Map types +- Complex structured data + +For structured configuration using TOML sections with record types, use `BAL_CONFIG_FILES` or `BAL_CONFIG_DATA` instead of individual environment variables. +::: + +### Configuration precedence in practice + +Example showing all three configuration methods: + +```ballerina +configurable int port = 8080; // Default +``` + +```toml +# Config.toml +port = 9090 +``` + +```bash +# Environment variable (highest priority) +export BAL_CONFIG_VAR_PORT=7777 + +# Command-line (medium priority) +java -jar app.jar -Cport=6666 +``` + +**Result:** `port = 7777` (environment variable wins) + +If `BAL_CONFIG_VAR_PORT` is not set: +- With `-Cport=6666`: Result is `6666` +- Without command-line arg: Result is `9090` (from Config.toml) +- Without Config.toml: Result is `8080` (default) ## Kubernetes ConfigMaps and secrets @@ -153,8 +306,15 @@ metadata: name: integration-secrets type: Opaque stringData: - BAL_DB_PASSWORD: "s3cur3p@ss" - BAL_API_KEY: "ak_xxxxxxxxxxxxx" + BAL_CONFIG_VAR_DBPASSWORD: "s3cur3p@ss" + BAL_CONFIG_VAR_APIKEY: "ak_xxxxxxxxxxxxx" +``` + +For module-level variables like `[database].password`, use the full path: + +```yaml +stringData: + BAL_CONFIG_VAR_MY_INTEGRATION_DATABASE_PASSWORD: "s3cur3p@ss" ``` ### Mount in deployment @@ -209,30 +369,6 @@ host = "smtp.example.com" port = 587 ``` -## Configuration encryption - -Encrypt sensitive values in `Config.toml`: - -```bash -bal encrypt -Enter value: -Enter secret: -Encrypted value: encrypted:aBcDeFgHiJkLmNoPqRsTuV== -``` - -Use the encrypted value in `Config.toml`: - -```toml -[db] -password = "encrypted:aBcDeFgHiJkLmNoPqRsTuV==" -``` - -At runtime, provide the decryption key: - -```bash -BAL_CONFIG_SECRET_KEY=my-secret-key java -jar my_integration.jar -``` - ## Configuration validation Ballerina validates configurations at startup. If a required configurable has no value, the application fails to start with a clear error: From 16f1b838f866cafae8704551f9a4849d2a6edf97 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 14:52:38 +0530 Subject: [PATCH 3/6] Remove reduntant documentation pages --- .../deploy-operate/deploy/aws-azure-gcp.md | 283 ------------------ en/docs/deploy-operate/deploy/environments.md | 240 --------------- .../deploy/managing-configurations.md | 1 - .../deploy/scaling-high-availability.md | 2 - en/docs/deploy/overview.md | 2 - en/sidebars.ts | 2 - 6 files changed, 530 deletions(-) delete mode 100644 en/docs/deploy-operate/deploy/aws-azure-gcp.md delete mode 100644 en/docs/deploy-operate/deploy/environments.md diff --git a/en/docs/deploy-operate/deploy/aws-azure-gcp.md b/en/docs/deploy-operate/deploy/aws-azure-gcp.md deleted file mode 100644 index 65ec23913d..0000000000 --- a/en/docs/deploy-operate/deploy/aws-azure-gcp.md +++ /dev/null @@ -1,283 +0,0 @@ ---- -sidebar_position: 4 -title: Deploy to AWS / Azure / GCP -description: Deploy integrations to major cloud providers. ---- - -# Deploy to AWS / Azure / GCP - -Deploy your WSO2 Integrator projects to major cloud providers using container services, Kubernetes, or serverless platforms. - -## General approach - -Regardless of the cloud provider, the deployment process follows a common pattern: - -1. **Build** the Ballerina project with `bal build` to produce an executable JAR and Docker artifacts -2. **Build a Docker image** from the generated Dockerfile -3. **Push the image** to a container registry -4. **Deploy** to the target compute service - -Ensure your project has a `Cloud.toml` for Docker artifact generation: - -```toml -# Cloud.toml -[container.image] -repository = "my-registry" -name = "wso2-integrator-app" -tag = "latest" -``` - -## AWS - -### ECS deployment - -Amazon Elastic Container Service (ECS) runs your integration as a containerized task. Use Fargate for serverless container execution. - -Push the image to Amazon ECR: - -```bash -# Authenticate to ECR -aws ecr get-login-password --region us-east-1 | \ - docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com - -# Tag and push -docker tag wso2-integrator-app:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/wso2-integrator-app:latest -docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/wso2-integrator-app:latest -``` - -Create an ECS task definition: - -```json -{ - "family": "wso2-integrator-app", - "networkMode": "awsvpc", - "requiresCompatibilities": ["FARGATE"], - "cpu": "512", - "memory": "1024", - "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole", - "containerDefinitions": [ - { - "name": "app", - "image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/wso2-integrator-app:latest", - "portMappings": [ - { - "containerPort": 9090, - "protocol": "tcp" - } - ], - "environment": [ - { - "name": "BAL_CONFIG_FILES", - "value": "/config/Config.toml" - } - ], - "secrets": [ - { - "name": "BAL_CONFIG_VAR_MY_MODULE_DB_PASSWORD", - "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:db-password" - } - ], - "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-group": "/ecs/wso2-integrator-app", - "awslogs-region": "us-east-1", - "awslogs-stream-prefix": "ecs" - } - } - } - ] -} -``` - -Deploy the service: - -```bash -aws ecs create-service \ - --cluster integrations \ - --service-name wso2-integrator-app \ - --task-definition wso2-integrator-app:1 \ - --desired-count 2 \ - --launch-type FARGATE \ - --network-configuration "awsvpcConfiguration={subnets=[subnet-abc123],securityGroups=[sg-abc123],assignPublicIp=ENABLED}" -``` - -### EKS deployment - -Amazon Elastic Kubernetes Service (EKS) provides a managed Kubernetes environment. After pushing your image to ECR, apply standard Kubernetes manifests: - -```bash -# Configure kubectl for EKS -aws eks update-kubeconfig --name my-cluster --region us-east-1 - -# Deploy -kubectl apply -f k8s/deployment.yaml -kubectl apply -f k8s/service.yaml -``` - -### Lambda considerations - -AWS Lambda can run Ballerina integrations for event-driven workloads with low traffic. Package the JAR as a Lambda function using a custom Java 17 runtime. Note that Lambda has a cold start penalty and a 15-minute execution timeout, making it best suited for short-lived, event-triggered integrations rather than long-running HTTP services. - -## Azure - -### AKS deployment - -Azure Kubernetes Service (AKS) provides managed Kubernetes. Push your image to Azure Container Registry (ACR) and deploy: - -```bash -# Authenticate to ACR -az acr login --name myregistry - -# Tag and push -docker tag wso2-integrator-app:latest myregistry.azurecr.io/wso2-integrator-app:latest -docker push myregistry.azurecr.io/wso2-integrator-app:latest - -# Configure kubectl for AKS -az aks get-credentials --resource-group my-rg --name my-cluster - -# Deploy -kubectl apply -f k8s/deployment.yaml -kubectl apply -f k8s/service.yaml -``` - -### Container apps - -Azure Container Apps provides a serverless container platform with built-in scaling and ingress: - -```bash -# Create a Container App -az containerapp create \ - --name wso2-integrator-app \ - --resource-group my-rg \ - --environment my-env \ - --image myregistry.azurecr.io/wso2-integrator-app:latest \ - --target-port 9090 \ - --ingress external \ - --min-replicas 1 \ - --max-replicas 5 \ - --cpu 0.5 \ - --memory 1.0Gi \ - --env-vars "BAL_CONFIG_FILES=/config/Config.toml" - -# Set secrets -az containerapp secret set \ - --name wso2-integrator-app \ - --resource-group my-rg \ - --secrets db-password=s3cret - -# Reference secrets as environment variables -az containerapp update \ - --name wso2-integrator-app \ - --resource-group my-rg \ - --set-env-vars "BAL_CONFIG_VAR_MY_MODULE_DB_PASSWORD=secretref:db-password" -``` - -## GCP - -### GKE deployment - -Google Kubernetes Engine (GKE) provides managed Kubernetes. Push to Google Artifact Registry and deploy: - -```bash -# Authenticate to Artifact Registry -gcloud auth configure-docker us-central1-docker.pkg.dev - -# Tag and push -docker tag wso2-integrator-app:latest us-central1-docker.pkg.dev/my-project/my-repo/wso2-integrator-app:latest -docker push us-central1-docker.pkg.dev/my-project/my-repo/wso2-integrator-app:latest - -# Configure kubectl for GKE -gcloud container clusters get-credentials my-cluster --zone us-central1-a - -# Deploy -kubectl apply -f k8s/deployment.yaml -kubectl apply -f k8s/service.yaml -``` - -### Cloud run - -Google Cloud Run provides a fully managed serverless container platform: - -```bash -# Deploy to Cloud Run -gcloud run deploy wso2-integrator-app \ - --image us-central1-docker.pkg.dev/my-project/my-repo/wso2-integrator-app:latest \ - --platform managed \ - --region us-central1 \ - --port 9090 \ - --min-instances 1 \ - --max-instances 10 \ - --memory 512Mi \ - --cpu 1 \ - --set-env-vars "BAL_CONFIG_FILES=/config/Config.toml" \ - --set-secrets "BAL_CONFIG_VAR_MY_MODULE_DB_PASSWORD=db-password:latest" -``` - -Cloud Run scales to zero when there is no traffic and scales up automatically based on request concurrency. - -## Cloud-Specific configuration - -Customize `Cloud.toml` for each provider: - -```toml -# Cloud.toml for AWS EKS -[container.image] -repository = "123456789012.dkr.ecr.us-east-1.amazonaws.com" -name = "wso2-integrator-app" -tag = "v1.0.0" - -[cloud.deployment] -min_memory = "256Mi" -max_memory = "512Mi" -min_cpu = "250m" -max_cpu = "500m" - -[[cloud.config.envs]] -key_ref = "BAL_CONFIG_FILES" -config_name = "integrator-config" - -[[cloud.config.secrets]] -key_ref = "DB_PASSWORD" -secret_name = "integrator-secrets" -``` - -## Networking and service discovery - -### Service mesh (Istio) - -In Kubernetes environments, use Istio for traffic management, mutual TLS, and observability: - -```yaml -# istio-virtual-service.yaml -apiVersion: networking.istio.io/v1beta1 -kind: VirtualService -metadata: - name: wso2-integrator-app -spec: - hosts: - - wso2-integrator-service - http: - - route: - - destination: - host: wso2-integrator-service - port: - number: 80 - timeout: 30s - retries: - attempts: 3 - perTryTimeout: 10s -``` - -### DNS-Based service discovery - -For non-Kubernetes environments (ECS, VM-based), use cloud-native service discovery: - -- **AWS**: Use AWS Cloud Map or Route 53 service discovery -- **Azure**: Use Azure DNS or Traffic Manager -- **GCP**: Use Cloud DNS or Traffic Director - -## What's next - -- [VM Deployment](../../deploy/self-hosted/vm-deployment.md) -- Develop and test before deploying -- [Scaling & High Availability](scaling-high-availability.md) -- Configure scaling and resilience diff --git a/en/docs/deploy-operate/deploy/environments.md b/en/docs/deploy-operate/deploy/environments.md deleted file mode 100644 index fa42f99262..0000000000 --- a/en/docs/deploy-operate/deploy/environments.md +++ /dev/null @@ -1,240 +0,0 @@ ---- -sidebar_position: 5 -title: Environments -description: Manage Dev, Test, and Prod environments with configuration promotion. ---- - -# Environments (Dev, Test, Prod) - -Manage environment-specific configuration to promote your integrations safely from development through testing to production. - -## Promotion workflow - -A typical promotion workflow moves your integration through three stages: - -``` -Development --> Testing --> Production -``` - -Each environment uses the same compiled artifact (JAR or Docker image) but with different configuration values. This ensures that the code tested in staging is identical to what runs in production -- only the configuration changes. - -### Recommended workflow - -1. **Development** -- Engineers run locally or deploy to a shared dev environment. Configuration points to sandbox APIs, local databases, and debug-level logging. -2. **Testing** -- The built artifact is deployed to a testing environment with production-like configuration. Integration tests and end-to-end tests run here. -3. **Production** -- After testing passes and approval is granted, the same artifact is promoted to production with production credentials and settings. - -## Environment-Specific Config.toml - -Ballerina uses `Config.toml` for runtime configuration. Maintain separate configuration files for each environment: - -``` -project-root/ - Config.toml # Default (local development) - config/ - dev-Config.toml - test-Config.toml - prod-Config.toml -``` - -### Development configuration - -```toml -# config/dev-Config.toml -[orderService] -port = 9090 -logLevel = "DEBUG" - -[orderService.database] -host = "localhost" -port = 3306 -name = "orders_dev" -user = "dev_user" -password = "dev_password" - -[orderService.externalApi] -baseUrl = "https://sandbox.api.example.com" -apiKey = "dev-key-12345" -timeoutSeconds = 30 -``` - -### Testing configuration - -```toml -# config/test-Config.toml -[orderService] -port = 9090 -logLevel = "INFO" - -[orderService.database] -host = "db-test.internal.example.com" -port = 3306 -name = "orders_test" -user = "test_user" -password = "${TEST_DB_PASSWORD}" - -[orderService.externalApi] -baseUrl = "https://staging.api.example.com" -apiKey = "${TEST_API_KEY}" -timeoutSeconds = 15 -``` - -### Production configuration - -```toml -# config/prod-Config.toml -[orderService] -port = 9090 -logLevel = "WARN" - -[orderService.database] -host = "db-prod.internal.example.com" -port = 3306 -name = "orders_prod" -user = "prod_user" -password = "${PROD_DB_PASSWORD}" - -[orderService.externalApi] -baseUrl = "https://api.example.com" -apiKey = "${PROD_API_KEY}" -timeoutSeconds = 10 -``` - -## Environment variables per target - -Override configuration values using environment variables without modifying `Config.toml` files. This is the recommended approach for secrets in containerized deployments. - -### Configurable variables in Ballerina - -Declare configurable variables in your Ballerina code: - -```ballerina -configurable int port = 9090; -configurable string dbHost = "localhost"; -configurable string dbPassword = ?; // Required, no default -``` - -### Setting values via environment variables - -```bash -# Convention: BAL_CONFIG_VAR__ -export BAL_CONFIG_VAR_ORDER_SERVICE_PORT=8080 -export BAL_CONFIG_VAR_ORDER_SERVICE_DB_HOST=db-prod.internal.example.com -export BAL_CONFIG_VAR_ORDER_SERVICE_DB_PASSWORD=s3cret -``` - -### Kubernetes ConfigMaps and secrets - -In Kubernetes, use ConfigMaps for non-sensitive values and Secrets for credentials: - -```yaml -# k8s/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: integrator-config - namespace: production -data: - Config.toml: | - [orderService] - port = 9090 - logLevel = "WARN" - [orderService.database] - host = "db-prod.internal.example.com" - port = 3306 - name = "orders_prod" -``` - -```yaml -# k8s/secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: integrator-secrets - namespace: production -type: Opaque -stringData: - DB_PASSWORD: "s3cret-prod-password" - API_KEY: "prod-api-key-67890" -``` - -Mount the ConfigMap and inject secrets as environment variables in your deployment: - -```yaml -# k8s/deployment.yaml -spec: - containers: - - name: app - env: - - name: BAL_CONFIG_FILES - value: "/config/Config.toml" - - name: BAL_CONFIG_VAR_ORDER_SERVICE_DB_PASSWORD - valueFrom: - secretKeyRef: - name: integrator-secrets - key: DB_PASSWORD - volumeMounts: - - name: config - mountPath: /config - volumes: - - name: config - configMap: - name: integrator-config -``` - -## Blue-Green and canary deployments - -### Blue-Green deployment - -Run two identical environments (blue and green). Route traffic to the active one and deploy updates to the inactive one. After verification, switch traffic. - -```bash -# Deploy new version to the inactive (green) environment -kubectl apply -f k8s/green/deployment.yaml - -# Verify the green deployment is healthy -kubectl rollout status deployment/integrator-green -n production - -# Switch traffic from blue to green -kubectl patch service integrator-service -n production \ - -p '{"spec":{"selector":{"version":"green"}}}' - -# After verification, scale down the old (blue) deployment -kubectl scale deployment/integrator-blue --replicas=0 -n production -``` - -### Canary deployment - -Route a small percentage of traffic to the new version. Gradually increase if metrics are healthy. - -```yaml -# k8s/canary-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: integrator-canary - namespace: production -spec: - replicas: 1 # Small fraction of total replicas - selector: - matchLabels: - app: integrator - track: canary - template: - metadata: - labels: - app: integrator - track: canary - spec: - containers: - - name: app - image: registry.example.com/integrator:v2.0.0 -``` - -Use a single Kubernetes Service with a shared label (`app: integrator`) so both the stable and canary deployments receive traffic proportional to their replica count. - -## What's next - -- [Scaling & High Availability](scaling-high-availability.md) -- Configure scaling and resilience -- [Secrets & Encryption](../secure/secrets-encryption.md) -- Secure your configuration values -- [CI/CD Pipelines](../cicd/github-actions.md) -- Automate environment promotions diff --git a/en/docs/deploy-operate/deploy/managing-configurations.md b/en/docs/deploy-operate/deploy/managing-configurations.md index b623820e8b..5d6f5008ed 100644 --- a/en/docs/deploy-operate/deploy/managing-configurations.md +++ b/en/docs/deploy-operate/deploy/managing-configurations.md @@ -397,6 +397,5 @@ configurable "DEBUG"|"INFO"|"WARN"|"ERROR" logLevel = "INFO"; // Enum constraint ## What's next -- [Environments](environments.md) -- Manage Dev, Test, and Prod promotion workflows - [Secrets & Encryption](../secure/secrets-encryption.md) -- Advanced secrets management with Vault - [Containerized Deployment](../../deploy/self-hosted/containerized-deployment.md) -- ConfigMap and Secret patterns for Docker, Kubernetes, and OpenShift diff --git a/en/docs/deploy-operate/deploy/scaling-high-availability.md b/en/docs/deploy-operate/deploy/scaling-high-availability.md index d59522f45e..1ede14ce60 100644 --- a/en/docs/deploy-operate/deploy/scaling-high-availability.md +++ b/en/docs/deploy-operate/deploy/scaling-high-availability.md @@ -312,6 +312,4 @@ The `preStop` sleep ensures the pod is removed from the Service endpoints before ## What's next -- [Environments](environments.md) -- Manage configuration across environments -- [Deploy to AWS / Azure / GCP](aws-azure-gcp.md) -- Cloud-specific scaling options - [Metrics](../observe/metrics-prometheus-grafana.md) -- Monitor scaling behavior with Prometheus diff --git a/en/docs/deploy/overview.md b/en/docs/deploy/overview.md index 9184ff1e1e..f507ac6b95 100644 --- a/en/docs/deploy/overview.md +++ b/en/docs/deploy/overview.md @@ -17,12 +17,10 @@ WSO2 Integrator supports multiple deployment targets. Choose the one that fits y - **[VM Deployment](./self-hosted/vm-deployment.md)** — Deploy your integration to a virtual machine or bare-metal server as a standalone JAR file. - **[Containerized Deployment](./self-hosted/containerized-deployment.md)** — Package your integration as a container and deploy it to Docker, Kubernetes, or Red Hat OpenShift. - **[Serverless deployment](../deploy-operate/deploy/serverless-deployment.md)** — Run integrations as serverless functions. -- **[AWS, Azure, and GCP](../deploy-operate/deploy/aws-azure-gcp.md)** — Deploy to major cloud providers using native services. - **[GraalVM native images](../deploy-operate/deploy/graalvm-native-images.md)** — Compile your integration to a native binary for faster startup and lower memory usage. ## Configuration and scaling -- **[Environments](../deploy-operate/deploy/environments.md)** — Manage dev, staging, and production environment configurations. - **[Managing configurations](../deploy-operate/deploy/managing-configurations.md)** — Externalize and manage runtime configuration values. - **[Scaling and high availability](../deploy-operate/deploy/scaling-high-availability.md)** — Design your deployment for resilience and scale. - **[Capacity planning](../deploy-operate/capacity-planning/overview.md)** — Estimate resource requirements and plan deployment sizing. diff --git a/en/sidebars.ts b/en/sidebars.ts index 4a1ec7a12c..8711483f3a 100644 --- a/en/sidebars.ts +++ b/en/sidebars.ts @@ -1907,9 +1907,7 @@ const sidebars: SidebarsConfig = { 'deploy/self-hosted/vm-deployment', 'deploy/self-hosted/containerized-deployment', 'deploy-operate/deploy/serverless-deployment', - 'deploy-operate/deploy/aws-azure-gcp', 'deploy-operate/deploy/graalvm-native-images', - 'deploy-operate/deploy/environments', 'deploy-operate/deploy/managing-configurations', 'deploy-operate/deploy/scaling-high-availability', ], From ff17be4462dc6f818df97ad73532b7034e6bb0b8 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 15:27:30 +0530 Subject: [PATCH 4/6] Update serverless deployment guide --- .../deploy/serverless-deployment.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/en/docs/deploy-operate/deploy/serverless-deployment.md b/en/docs/deploy-operate/deploy/serverless-deployment.md index 6b2bcfbd77..7dac3b61aa 100644 --- a/en/docs/deploy-operate/deploy/serverless-deployment.md +++ b/en/docs/deploy-operate/deploy/serverless-deployment.md @@ -74,6 +74,14 @@ service "mycontainer/{name}" on new af:BlobListener({path: "mycontainer/{name}"} bal build ``` +:::note +The `--cloud` flag is optional for Azure Functions. The compiler auto-detects the Azure Functions extension and defaults to `--cloud="azure_functions"`. You can explicitly specify it to avoid the warning: + +```bash +bal build --cloud="azure_functions" +``` +::: + The compiler extension generates the function artifacts automatically: ``` @@ -200,6 +208,14 @@ public function processDynamoDB(lambda:Context ctx, bal build ``` +:::note +The `--cloud` flag is optional for AWS Lambda. The compiler auto-detects the Lambda extension. You can explicitly specify it if needed: + +```bash +bal build --cloud="aws_lambda" +``` +::: + The compiler extension runs automatically and generates the deployment package: ``` @@ -329,4 +345,4 @@ az functionapp plan create \ - [GraalVM Native Images](graalvm-native-images.md) — Compile to native binaries for minimal cold start - [Managing Configurations](managing-configurations.md) — Environment-specific configuration strategies -- [Deploy to AWS / Azure / GCP](aws-azure-gcp.md) — Container-based cloud deployments +- [Containerized Deployment](../../deploy/self-hosted/containerized-deployment.md) — Deploy as containers to Kubernetes or Docker From 31a722c8cfca700dc977a16a4f66134babd76af9 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 16:48:58 +0530 Subject: [PATCH 5/6] Fix configuration precedence order with verified testing --- .../deploy/managing-configurations.md | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/en/docs/deploy-operate/deploy/managing-configurations.md b/en/docs/deploy-operate/deploy/managing-configurations.md index 5d6f5008ed..21f7f6d743 100644 --- a/en/docs/deploy-operate/deploy/managing-configurations.md +++ b/en/docs/deploy-operate/deploy/managing-configurations.md @@ -16,8 +16,12 @@ Ballerina resolves configuration values from multiple sources, with the followin |----------|--------|---------| | 1 | Environment variables | `BAL_CONFIG_VAR_PORT=9090` | | 2 | Command-line arguments | `-Cport=9090` | -| 3 | `Config.toml` file(s) or `BAL_CONFIG_DATA` | `port = 9090` | -| 4 | Default values in code | `configurable int port = 8080;` | +| 3 | `BAL_CONFIG_FILES` | `BAL_CONFIG_FILES=prod.toml` | +| 4 | `BAL_CONFIG_DATA` | `BAL_CONFIG_DATA='port=9090'` | +| 5 | `Config.toml` (default file) | `port = 9090` | +| 6 | Default values in code | `configurable int port = 8080;` | + +When both `BAL_CONFIG_FILES` and `BAL_CONFIG_DATA` are set, `BAL_CONFIG_FILES` takes precedence. The default `Config.toml` in the current directory is only used when neither `BAL_CONFIG_FILES` nor `BAL_CONFIG_DATA` is specified. ## Defining configurable values @@ -249,31 +253,39 @@ For structured configuration using TOML sections with record types, use `BAL_CON ### Configuration precedence in practice -Example showing all three configuration methods: +Example demonstrating the complete precedence order: ```ballerina -configurable int port = 8080; // Default +configurable int port = 8080; // Priority 6: Default value ``` ```toml -# Config.toml +# Config.toml (Priority 5: Default file) port = 9090 ``` ```bash -# Environment variable (highest priority) -export BAL_CONFIG_VAR_PORT=7777 +# Priority 4: BAL_CONFIG_DATA +export BAL_CONFIG_DATA='port=7777' + +# Priority 3: BAL_CONFIG_FILES (overrides BAL_CONFIG_DATA) +export BAL_CONFIG_FILES=custom.toml # contains port=6666 + +# Priority 2: Command-line (overrides BAL_CONFIG_FILES) +java -jar app.jar -Cport=5555 -# Command-line (medium priority) -java -jar app.jar -Cport=6666 +# Priority 1: Environment variable (HIGHEST - overrides everything) +export BAL_CONFIG_VAR_PORT=4444 ``` -**Result:** `port = 7777` (environment variable wins) +**Result:** `port = 4444` (environment variable wins) -If `BAL_CONFIG_VAR_PORT` is not set: -- With `-Cport=6666`: Result is `6666` -- Without command-line arg: Result is `9090` (from Config.toml) -- Without Config.toml: Result is `8080` (default) +**Precedence cascade:** +- If `BAL_CONFIG_VAR_PORT` not set → uses command-line value `5555` +- If no command-line → uses `BAL_CONFIG_FILES` value `6666` +- If no `BAL_CONFIG_FILES` → uses `BAL_CONFIG_DATA` value `7777` +- If no `BAL_CONFIG_DATA` → uses `Config.toml` value `9090` +- If no `Config.toml` → uses default value `8080` ## Kubernetes ConfigMaps and secrets From f5d693360b08aa13f2ebb3e3c7713bda10000ed9 Mon Sep 17 00:00:00 2001 From: dilhasha Date: Mon, 8 Jun 2026 17:07:07 +0530 Subject: [PATCH 6/6] Remove cloud provider-specific content from serverless deployment guide --- .../deploy/serverless-deployment.md | 106 ++---------------- 1 file changed, 9 insertions(+), 97 deletions(-) diff --git a/en/docs/deploy-operate/deploy/serverless-deployment.md b/en/docs/deploy-operate/deploy/serverless-deployment.md index 7dac3b61aa..81be6e314b 100644 --- a/en/docs/deploy-operate/deploy/serverless-deployment.md +++ b/en/docs/deploy-operate/deploy/serverless-deployment.md @@ -8,14 +8,6 @@ description: Deploy integrations as serverless functions on AWS Lambda and Azure WSO2 Integrator projects can be deployed as serverless functions, enabling event-driven scaling with zero infrastructure management. Ballerina supports AWS Lambda and Azure Functions as first-class deployment targets via compiler extensions that generate deployment artifacts automatically at build time. -## Overview - -| Feature | AWS Lambda | Azure Functions | -|---------|-----------|-----------------| -| Trigger Types | HTTP (API Gateway), S3, SQS, DynamoDB Streams, SES | HTTP, Timer, Blob Storage, Queue, CosmosDB | -| Max Execution | 15 minutes | 10 minutes (Consumption plan) | -| Runtime | Custom runtime (provided) | Java 21, Windows hosting | - ## Azure Functions ### Prerequisites @@ -112,45 +104,14 @@ func start --script-root target/azure_functions --java ### Step 4: Deploy to Azure -First create the required Azure resources: +Deploy using the Azure Functions Core Tools: ```bash -az group create --name integration-rg --location eastus - -az storage account create \ - --name integrationstorage \ - --location eastus \ - --resource-group integration-rg \ - --sku Standard_LRS - -az functionapp create \ - --resource-group integration-rg \ - --consumption-plan-location eastus \ - --runtime java \ - --runtime-version 21 \ - --functions-version 4 \ - --name my-integration-func \ - --storage-account integrationstorage \ - --os-type Windows -``` - -Then deploy using the Azure Functions Core Tools: - -```bash -func azure functionapp publish my-integration-func \ +func azure functionapp publish \ --script-root target/azure_functions ``` -### Azure configuration - -Set application settings for environment-specific configuration: - -```bash -az functionapp config appsettings set \ - --name my-integration-func \ - --resource-group integration-rg \ - --settings "DB_HOST=db.internal.example.com" "DB_PORT=5432" -``` +Refer to the [Azure Functions documentation](https://learn.microsoft.com/en-us/azure/azure-functions/) for creating and configuring Azure Function Apps. ## AWS Lambda @@ -267,68 +228,19 @@ aws lambda update-function-code \ --zip-file fileb://target/aws_lambda/aws-ballerina-lambda-functions.zip ``` -### Step 4: Add an API Gateway trigger - -```bash -aws apigatewayv2 create-api \ - --name order-api \ - --protocol-type HTTP \ - --target arn:aws:lambda:us-east-1:123456789012:function:processOrder -``` - -### Lambda configuration - -Configure via environment variables in the Lambda console or deployment script: - -```bash -aws lambda update-function-configuration \ - --function-name processOrder \ - --environment "Variables={DB_HOST=db.internal.example.com,DB_PORT=5432}" -``` - -For secrets, reference AWS Secrets Manager from your application code rather than embedding values in environment variables. +Refer to the [AWS Lambda documentation](https://docs.aws.amazon.com/lambda/) for deployment configuration and trigger setup. ## Reducing cold start times ### Use GraalVM native images -Compile to a native binary to reduce startup time. - -For AWS Lambda: +Compile to a native binary to reduce startup time: ```bash bal build --graalvm ``` -For Azure Functions: - -```bash -bal build --graalvm --cloud="azure_functions" -``` - -### Provisioned concurrency (AWS) - -Keep warm instances ready to handle requests: - -```bash -aws lambda put-provisioned-concurrency-config \ - --function-name processOrder \ - --qualifier production \ - --provisioned-concurrent-executions 5 -``` - -### Premium plan (Azure) - -Use the Premium plan for pre-warmed instances: - -```bash -az functionapp plan create \ - --name premium-plan \ - --resource-group integration-rg \ - --location eastus \ - --sku EP1 \ - --min-instances 1 -``` +The compiler auto-detects the serverless platform and generates the appropriate native image artifacts. ## Best practices @@ -337,9 +249,9 @@ az functionapp plan create \ | Function Size | Keep functions focused on a single operation | | Dependencies | Minimize package dependencies to reduce deployment size | | Timeouts | Set appropriate timeouts based on expected execution time | -| Secrets | Use cloud-native secret managers (Secrets Manager, Key Vault) | -| Observability | Enable X-Ray (AWS) or Application Insights (Azure) | -| VPC Access | Configure VPC/VNet only when accessing private resources | +| Secrets | Use cloud-native secret managers for sensitive configuration | +| Observability | Enable platform observability features for monitoring and tracing | +| Network Access | Configure network access only when required for private resources | ## What's next