Appearance
Fooj Environments
Section: 17 — Fooj
Last Updated: 2026-05-30
Scope: Fooj staging and production environments, NAT GW IP, domain configuration
Overview
Fooj runs two environments: staging and production. Unlike the ERP platform which has five environments (dev, stage, preprod, uat, production), Fooj uses a simpler two-stage model appropriate for its release cadence.
| Environment | Purpose | Branch |
|---|---|---|
stg | Integration testing, UAT, demo | stage / staging |
prod | Live production traffic | main / production |
Environment Summary
Staging
| Property | Value |
|---|---|
| Subscription | f2340b90-2a00-4551-aabc-6e1776e82077 |
| Resource Group (containers) | fooj-stg-containers-rg |
| ACA Environment | fooj-stg-cae |
| ACR | foojstgacr |
| Key Vault | fooj-stg-kv |
| Outbound NAT IP | 20.26.0.39 |
| Primary Domain | stg.fooj.sa |
| Azure region | UK South |
Production
| Property | Value |
|---|---|
| Subscription | f2340b90-2a00-4551-aabc-6e1776e82077 |
| Resource Group (containers) | fooj-prod-containers-rg |
| ACA Environment | fooj-prod-cae |
| ACR | foojprodacr |
| Key Vault | fooj-prod-kv |
| Outbound NAT IP | 20.26.0.39 |
| Primary Domain | fooj.sa |
| Azure region | UK South |
NAT Gateway — Shared Egress IP
Both Fooj environments and ERP stage + production share the same outbound IP:
Shared NAT Gateway IP
20.26.0.39 — Used by Fooj staging, Fooj production, ERP staging, and ERP production for all outbound internet traffic.
This IP is the one to provide to any third-party service that requires IP allowlisting (payment processors, SMS gateways, external APIs).
Init Container Gotcha
When initialising Fooj containers for the first time, the NAT Gateway route takes a few seconds to propagate after the ACA environment's VNet integration is configured. During this window, outbound calls from init containers may fail.
Init container network timing
If an init container that performs an outbound call (e.g., database connectivity check, secret resolution) fails immediately after a fresh ACA environment provision, wait 60 seconds and retry. The NAT Gateway route is eventually consistent — it is not instantaneous.
Workaround used in pipelines:
bash
# In the init container entrypoint script
for i in $(seq 1 10); do
curl -sf https://graph.microsoft.com/v1.0/$metadata && break
echo "Attempt $i: waiting for network..."
sleep 10
doneDomain Configuration
Staging — stg.fooj.sa
| Record Type | Name | Value |
|---|---|---|
| CNAME | stg.fooj.sa | fooj-stg-cae.{hash}.uksouth.azurecontainerapps.io |
| TXT | asuid.stg.fooj.sa | ACA domain verification token |
Production — fooj.sa
| Record Type | Name | Value |
|---|---|---|
| A | @ | Azure Front Door anycast IP (if AFD is used) |
| CNAME | www.fooj.sa | fooj-prod-cae.{hash}.uksouth.azurecontainerapps.io |
| TXT | asuid.fooj.sa | ACA domain verification token |
Custom Domain Setup on ACA
bash
# Add custom domain to the container app
az containerapp hostname add \
--name fooj-ssr \
--resource-group fooj-stg-containers-rg \
--hostname stg.fooj.sa
# Bind a managed certificate
az containerapp hostname bind \
--name fooj-ssr \
--resource-group fooj-stg-containers-rg \
--hostname stg.fooj.sa \
--environment fooj-stg-cae \
--validation-method CNAMEACA provisions and renews the TLS certificate automatically once the CNAME record is in place.
Environment Variables
Environment-specific configuration is stored in Key Vault and referenced via keyvaultref: in the ACA container app's environment variable settings.
Staging Key Vault secrets (representative list)
| KV Secret Name | Environment Variable | Description |
|---|---|---|
Fooj--DbConnection | DATABASE_URL | PostgreSQL connection string |
Fooj--RedisConnection | REDIS_URL | Redis cache connection |
Fooj--JwtSecret | JWT_SECRET | Token signing key |
Fooj--BlobStorage | AZURE_BLOB_CONNECTION | Storage account connection |
Fooj--SendgridKey | SENDGRID_API_KEY | Email delivery |
Promoting secrets from staging to production
Secrets are not copied automatically. Each environment maintains its own Key Vault with independently managed secrets. A promotion checklist in the CI/CD runbook ensures production secrets are set before deploying to production.
Scaling Configuration
Staging
json
{
"minReplicas": 0,
"maxReplicas": 3,
"scaleRules": [
{
"name": "http-scale",
"type": "http",
"metadata": { "concurrentRequests": "30" }
}
]
}Staging scales to zero when idle to save cost.
Production
json
{
"minReplicas": 2,
"maxReplicas": 20,
"scaleRules": [
{
"name": "http-scale",
"type": "http",
"metadata": { "concurrentRequests": "50" }
}
]
}Production maintains a minimum of 2 replicas to avoid cold-start latency for real users.
Health Checks
Both environments expose a /health endpoint on the SSR container:
bash
# Staging
curl https://stg.fooj.sa/health
# Production
curl https://fooj.sa/healthExpected response:
json
{
"status": "Healthy",
"checks": {
"database": "Healthy",
"redis": "Healthy"
}
}ACA liveness and readiness probes are configured to call /health every 30 seconds with a 5-second timeout.
Differences Between Environments
| Feature | Staging | Production |
|---|---|---|
| Min replicas | 0 (scale to zero) | 2 |
| Zone redundancy | No | Yes |
| ACR geo-replication | No | Yes |
| Debug logging | Enabled | Disabled |
| SSR cache TTL | 60 seconds | 300 seconds |
| CDN | Not configured | Azure CDN |