alawadi.cloudDocs
Guides

Add managed Postgres, MySQL, or Redis

Add a managed database to a project from the dashboard and link it into a container so the connection URL is injected automatically.

Add a database

Managed databases live inside your project and are reachable only over internal DNS. They are never exposed publicly. You create one in the dashboard, then link it to a container so the platform injects the connection URL (with credentials) into that container for you. You never see, copy, or set the password by hand.

The engines are fixed and managed: Postgres 16, MySQL 8.4, Redis 8.

Dashboard flow

Open Databases in the sidebar and click New database. Pick the project, the engine (PostgreSQL, MySQL, or Redis), a name, and reserved resources. Submit, and you land on the new database's detail page while it provisions.
On the detail page, use Link to container and choose a container app in the same project. The platform injects DATABASE_URL (Postgres/MySQL) or REDIS_URL (Redis) into that container and re-rolls it automatically.
Read the injected variable from your app's environment. No manual redeploy is needed: linking re-provisions the consumer for you.

1. Create the database

In the create dialog you set:

  • Project: the database joins this project and is reachable only by services in it.
  • Engine: PostgreSQL, MySQL, or Redis. The dialog shows the matching options:
    • PostgreSQL: version 16. Connects on port 5432 as DATABASE_URL.
    • MySQL: version 8.4. Connects on port 3306 as DATABASE_URL.
    • Redis: connects on port 6379 as REDIS_URL. A persistence toggle (on by default; off for a pure-cache instance) and an eviction policy (maxmemory_policy, default allkeys-lru).
  • Name: a friendly name; the dialog shows the slug it deploys as.
  • Resources: reserved CPU, memory, and storage (bounded, see below).

resources are bounded: cpu_milli 250-4000 (steps of 250), memory_mb 256-8192 (steps of 128), storage_gb 1-100. Out-of-range values are rejected. Each database runs as a single internal instance; replicas are not configurable.

2. Connect it to a container

You can connect from either side, and both do the same thing:

  • On the container page, open Connected services → Connect a database and pick a database in the same project.
  • On the database page, open Link to container and pick a container.

The database is the provider, the container is the consumer. The platform injects the connection variables into the container through a Kubernetes Secret reference and re-rolls it automatically. The credentials stay in the Secret. They never appear in plaintext env or in any API response, and you never set them by hand.

The connection is durable: it is re-applied on every change, whether env edits, scaling, autoscaling, or an image deploy (including from GitHub Actions), so a linked app stays connected across redeploys.

What gets injected (per framework)

The platform injects a standard set of variables, so the right name is already present for your stack:

EngineRead thisAlso injected
PostgresDATABASE_URLPGHOST PGPORT PGDATABASE PGUSER PGPASSWORD; SPRING_DATASOURCE_URL / _USERNAME / _PASSWORD
MySQLDATABASE_URLDB_HOST DB_PORT DB_NAME DB_USER DB_PASSWORD; SPRING_DATASOURCE_*
RedisREDIS_URLREDIS_HOST REDIS_PORT REDIS_PASSWORD

Node, Python, Go, Rails, and Django read DATABASE_URL; Java/Spring reads SPRING_DATASOURCE_URL. The container's Connected services card shows the exact variable names and a copy-paste snippet for your language, plus an Unlink action.

A managed database is only connectable to a backend container. Frontend bundles (VITE_* / REACT_APP_*) are built ahead of time and must never carry a database credential, so a database link is not offered for them.

3. Read the variable in your app

Once connected, your container rolls with the variables present. Read them the normal way from the environment (for example os.environ["DATABASE_URL"] or process.env.REDIS_URL).

Advanced: the API path

The same create and link flow is available over the API for automation and scripting. Authenticate every call with your account token in the Authorization: Bearer header, and get the PROJECT_ID from your project in the dashboard.

Create the database

Send the friendly name, the reserved resources, and (for Postgres/MySQL) a version. The platform slugifies the name, generates the credentials, and returns the new service's id and its internal connection host:

# Add managed Postgres to a project
curl -X POST https://api.alawadi.cloud/v1/projects/$PROJECT_ID/postgres \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "app-db",
    "version": "16",
    "resources": { "cpu_milli": 500, "memory_mb": 512, "storage_gb": 5 }
  }'

Swap the path segment for mysql or redis to create those engines instead:

  • postgres: version is 16. Connects on port 5432 as DATABASE_URL.
  • mysql: version is 8.4. Connects on port 3306 as DATABASE_URL.
  • redis: version is fixed; omit it. Connects on port 6379 as REDIS_URL. Optionally send "persistence": false for a pure-cache instance, or "maxmemory_policy" (one of noeviction, allkeys-lru, allkeys-lfu, allkeys-random, volatile-lru, volatile-lfu, volatile-random, volatile-ttl; default allkeys-lru) to set the eviction policy.

resources is required and bounded: cpu_milli 250-4000 (steps of 250), memory_mb 256-8192 (steps of 128), storage_gb 1-100. Out-of-range values return BAD_RESOURCES; an unsupported version returns BAD_VERSION, and a bad Redis policy returns BAD_MAXMEMORY_POLICY.

The 201 response wraps the new service and a connection block. The service id is what you link with, and the connection shows the internal host your app would use:

{
  "service": {
    "id": "11111111-1111-1111-1111-111111111111",
    "name": "app-db",
    "type": "postgres",
    "status": "provisioning"
  },
  "connection": {
    "host": "app-db-rw.<namespace>.svc.cluster.local:5432",
    "port": "5432",
    "env_var": "DATABASE_URL",
    "requires_auth": "true",
    "instructions": "Link this Postgres to a container to auto-inject DATABASE_URL (with credentials) into it."
  }
}

The connection block is also returned by GET /v1/containers/{containerID} for any database, so you can read the host and connection variable back later.

Pass the service IDs (the id field from each service, not its name) of the consumer container and the database as the provider, plus the link_type that matches the provider engine (postgres, mysql, or redis):

# Link the database into your web container
curl -X POST https://api.alawadi.cloud/v1/projects/$PROJECT_ID/service-links \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "consumer_service_id": "'"$WEB_CONTAINER_ID"'",
    "provider_service_id": "'"$DB_SERVICE_ID"'",
    "link_type": "postgres"
  }'

consumer_service_id, provider_service_id, and link_type are all required. The link_type is postgres, mysql, or redis, matching the provider engine (Postgres/MySQL inject DATABASE_URL; Redis injects REDIS_URL). The consumer must be a generic container in the same project. The 201 response returns the link, including the injected_env map.

To confirm a link exists, list them:

curl https://api.alawadi.cloud/v1/projects/$PROJECT_ID/service-links \
  -H "Authorization: Bearer $TOKEN"

See Managed Postgres, MySQL, and Redis for the connection model and host formats.

On this page