Service Configuration
Creating and configuring system services (MySQL, Redis, Elasticsearch, RabbitMQ) with the critical _merge flag.
Service Configuration
Service Configuration Overview
Two-Step Process
Step 1: Enable in services.yaml
Define service type, version, and disk space
Step 2: Map in app.yaml
Create relationships to make services accessible
Pro Cloud Limitation
services.yaml and relationship changes in app.yaml only affect Integration environment on Pro accounts!
To change services in Pro Staging or Production, you must file a support ticket. This does NOT apply to Starter hosting.
Basic Service Syntax
services.yaml Configuration
elasticsearch:
type: elasticsearch:6.5
disk: 1024
Configuration Elements
- Service name: Identifier (e.g., elasticsearch, rabbitmq)
- type: Service name with required version (servicename:version)
- disk: Disk allotment in megabytes (minimum 256MB)
Minimum Disk Space
If you don't specify enough disk space (minimum 256MB), you'll get strange errors:
- MySQL: "MySQL server has gone away" (not helpful!)
- Other services: Various cryptic failures
Mapping Services with Relationships
app.yaml Relationships
After configuring services in services.yaml, map them to useable "access points" in .magento.app.yaml:
relationships:
database: "mysql:mysql"
redis: "redis:redis"
elasticsearch: "elasticsearch:elasticsearch"
rabbitmq: "rabbitmq:rabbitmq"
Relationship Format
relationship_name: "service_name:endpoint"
- relationship_name: How your application references it
- service_name: Name from services.yaml
- endpoint: Service endpoint (usually matches service type)
The _merge Flag (Critical)
Understanding _merge Behavior
| _merge Setting | Behavior |
|---|---|
| _merge: true | Values are merged with app/etc/env.php |
| _merge not set (default) | Section in app/etc/env.php is overwritten |
Example: The Wrong Way (Without _merge)
.magento.env.yaml
stage:
deploy:
DATABASE_CONFIGURATION:
username: 'my_user'
Result in app/etc/env.php (BROKEN)
'db' => array (
'connection' => array (
'default' => array (
'username' => 'my_user'
// Missing: host, dbname, password!
)
),
),
Problem
Magento cannot connect to database - missing host, dbname, and password!
Example: The Right Way (With _merge)
.magento.env.yaml
stage:
deploy:
DATABASE_CONFIGURATION:
username: 'my_user'
_merge: true
Result in app/etc/env.php (CORRECT)
'db' => array (
'connection' => array (
'default' => array (
'username' => 'my_user', // Changed
'host' => 'database.internal', // Preserved
'dbname' => 'main', // Preserved
'password' => '', // Preserved
)
),
),
Solution
All configuration details are preserved and merged with your custom values!
Common Use Cases for _merge
- External database connection: Add external DB while preserving defaults
- Elasticsearch configuration: Specify custom connection details
- Table prefix: Add table_prefix without losing other config
- Any *_CONFIGURATION option: Safely extend configuration
Best Practice
Always use _merge: true when using *_CONFIGURATION variables unless you explicitly want to replace the entire section.
MySQL Configuration
Basic MySQL Setup
# .magento/services.yaml
mysql:
type: mysql:10.4
disk: 2048
# .magento.app.yaml
relationships:
database: "mysql:mysql"
Multiple MySQL Databases
Cloud can have multiple databases by specifying unique endpoints (users):
# .magento/services.yaml
mysql:
type: mysql:10.4
disk: 2048
configuration:
schemas:
- main
- analytics
endpoints:
mysql:
default_schema: main
privileges:
main: admin
analytics: admin
readonly:
default_schema: main
privileges:
main: ro
analytics: ro
# .magento.app.yaml
relationships:
database: "mysql:mysql"
database_readonly: "mysql:readonly"
What This Creates
- mysql endpoint: Full admin privileges on both schemas
- readonly endpoint: Read-only (SELECT) on both schemas
Default Endpoint Behavior
By default, the endpoint is mysql. However, with default configuration, you can use any value or leave it empty for the username.
Redis Configuration
Prerequisites
To use Redis, ensure you configure:
runtime/extensions/redisin .magento.app.yamlrelationships/redisin .magento.app.yaml
Basic Redis Setup
# .magento/services.yaml
redis:
type: redis:6.0
disk: 256
# .magento.app.yaml
runtime:
extensions:
- redis
- xsl
- imagick
relationships:
redis: "redis:redis"
Accessing Redis Locally
Use SSH tunneling to connect from your local machine:
magento-cloud tunnel:open
Then connect with redis-cli:
redis-cli -h 127.0.0.1 -p [PORT_FROM_TUNNEL]
Elasticsearch Configuration
Basic Elasticsearch Setup
# .magento/services.yaml
elasticsearch:
type: elasticsearch:7.7
disk: 1024
# .magento.app.yaml
relationships:
elasticsearch: "elasticsearch:elasticsearch"
Configuring Elasticsearch Plugins
You can configure Elasticsearch plugins in services.yaml:
# .magento/services.yaml
elasticsearch:
type: elasticsearch:7.7
disk: 1024
configuration:
plugins:
- analysis-icu
- analysis-phonetic
Configuration Path
.magento/services.yaml → elasticsearch/configuration/plugins
RabbitMQ Configuration
Option 1: Cloud-Provided RabbitMQ
# .magento/services.yaml
rabbitmq:
type: rabbitmq:3.8
disk: 512
# .magento.app.yaml
relationships:
rabbitmq: "rabbitmq:rabbitmq"
Option 2: External Queue (via Environment Variable)
Use QUEUE_CONFIGURATION environment variable to specify an external queue:
# .magento.env.yaml
stage:
deploy:
QUEUE_CONFIGURATION:
amqp:
host: 'external-rabbitmq.example.com'
port: 5672
user: 'guest'
password: 'guest'
virtualhost: '/'
_merge: true
Choice
You can either allow Commerce Cloud to provide RabbitMQ, or use an external queue service.
Environment Configuration Variables
Available *_CONFIGURATION Options
| Variable | Purpose |
|---|---|
DATABASE_CONFIGURATION |
Customize database connection |
QUEUE_CONFIGURATION |
Configure message queue (RabbitMQ) |
CACHE_CONFIGURATION |
Configure cache backend (Redis) |
SESSION_CONFIGURATION |
Configure session storage (Redis) |
SEARCH_CONFIGURATION |
Configure search engine (Elasticsearch) |
Remember _merge!
Always include _merge: true with *_CONFIGURATION variables to preserve existing configuration.
Practical Experience Tasks
Hands-On Practice
- Configure two MySQL users: One with all privileges, another with SELECT-only access
- Set up Redis tunneling: Use magento-cloud tunnel:open and connect with redis-cli
- Add Elasticsearch plugin: Configure analysis-icu plugin
- Test _merge flag: Add custom DATABASE_CONFIGURATION with and without _merge to see the difference
Best Practices
Do's
- Always use _merge: true with *_CONFIGURATION
- Specify minimum 256MB disk for services
- Include redis extension in runtime/extensions
- Test in Integration before Staging/Production
- Use tunnel:open for local service access
- Document custom configurations
- File support ticket for Pro Staging/Production
Don'ts
- Don't use *_CONFIGURATION without _merge
- Don't specify less than 256MB disk
- Don't forget redis runtime extension
- Don't expect services.yaml to work in Pro Staging/Prod
- Don't skip relationship mapping
- Don't use incompatible service versions
- Don't forget to test configuration changes
Exam Tips
Key Points to Remember
- Basic syntax: type: servicename:version, disk: size_in_mb
- Minimum disk: 256MB (errors if less)
- Two-step process: Configure in services.yaml, map in app.yaml relationships
- Pro limitation: services.yaml only affects Integration (need support ticket for Staging/Production)
- Starter: No such limitation, works in all environments
- _merge: true: Merges with app/etc/env.php (CRITICAL!)
- _merge not set: Overwrites entire section (usually breaks things)
- MySQL endpoints: Can configure multiple users with different privileges
- MySQL default endpoint: mysql (can use any value with default config)
- Redis requirements: runtime/extensions/redis AND relationships/redis
- Redis access: Use magento-cloud tunnel:open, then redis-cli
- Elasticsearch plugins: Configure at elasticsearch/configuration/plugins
- RabbitMQ options: Cloud-provided OR external via QUEUE_CONFIGURATION
- *_CONFIGURATION variables: DATABASE, QUEUE, CACHE, SESSION, SEARCH
- Always use: _merge: true with *_CONFIGURATION variables