Blog

PHP Configuration Essentials for DreamFactory: Critical Settings You Need to Know

Written by Cody Lord | November 25, 2025

Summary

This guide focuses on the critical configurations every DreamFactory administrator must understand: memory_limit, upload_max_filesize, post_max_size, PHP-FPM worker settings, and the often-overlooked configuration hierarchy where pool settings override php.ini values.

Critical takeaway: If you modify php.ini but don't see changes, your PHP-FPM pool configuration (www.conf) is likely overriding your settings.

Why PHP Configuration Matters for DreamFactory

DreamFactory is a Laravel-based REST API platform. Common failures caused by misconfiguration:

  • File upload failuresupload_max_filesize too low
  • Memory exhaustionmemory_limit insufficient for large queries/transformations
  • Timeout errorsmax_execution_time too short for complex operations
  • Connection refused → PHP-FPM worker pool exhausted (pm.max_children)
  • Settings not taking effect → Pool configuration overriding php.ini

Critical PHP INI Settings

memory_limit

Default: 128M

It is always best to lean towards the lowest setting that works for your deployment, high values can rapidly consume server resources.

DreamFactory recommendations:

  • Development: 128M-256M minimum
  • Production (standard): 512M
  • Production (heavy workload): 1024M+

Why it matters: Schema introspection, large result sets, file processing, and API aggregation consume significant memory.

# /etc/php/8.3/fpm/php.ini
memory_limit = 1024M

upload_max_filesize and post_max_size

Defaults: 2M and 8M 

DreamFactory recommendations:

  • Standard: 100M
  • File-heavy workloads: 500M to 2G
Critical relationship: post_max_size must be ≥ upload_max_filesize (add 5-10M buffer)
# /etc/php/8.3/fpm/php.ini
upload_max_filesize = 100M
post_max_size = 105M

Also configure nginx/Apache:

# Nginx
client_max_body_size 100M;

# Apache
LimitRequestBody 104857600  # 100MB in bytes

max_execution_time

Default: 30 seconds

DreamFactory recommendations:

  • Standard API operations: 120 seconds
  • Long-running operations: 300 seconds
  • Background jobs: 600+ seconds
# /etc/php/8.3/fpm/php.ini
max_execution_time = 120

Align webserver timeouts:

# Nginx
fastcgi_read_timeout 180s;

# Apache
TimeOut 180

max_input_vars

Default: 1000

DreamFactory recommendation: 5000-10000

Why it matters: Complex API requests with nested JSON or bulk operations can exceed default.

# /etc/php/8.3/fpm/php.ini
max_input_vars = 5000

Critical PHP-FPM Settings

pm.max_children (Most Important Setting)

What it controls: Maximum simultaneous PHP worker processes.

Critical: If all workers are busy, new requests fail with "connect() to php-fpm.sock failed (Resource temporarily unavailable)".

Calculation formula:

pm.max_children = (Available RAM for PHP) / (Average PHP Process Memory)

Example calculation:

  • 8GB server, 2GB reserved for OS/MySQL/Redis = 6GB available
  • Average DreamFactory worker: 64MB
  • pm.max_children = 6144MB / 64MB = 96

Quick reference by server RAM:

  • 4GB RAM server: pm.max_children = 40
  • 8GB RAM server: pm.max_children = 80
  • 16GB RAM server: pm.max_children = 150
# /etc/php/8.3/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 80
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 2000

Process Manager Modes

Choose based on traffic pattern:

  • pm = static: Predictable load, consistent performance
  • pm = dynamic: Variable load, resource efficiency (recommended for most)
  • pm = ondemand: Development only, minimize resource usage

The Configuration Hierarchy Problem

Critical issue many administrators miss: PHP-FPM pool configuration overrides php.ini settings.

Configuration Precedence (highest to lowest):

  1. PHP-FPM pool config (/etc/php/8.3/fpm/pool.d/www.conf) ← Takes priority
  2. php.ini (/etc/php/8.3/fpm/php.ini)
  3. PHP compiled defaults

Example Problem:

You set in php.ini:

memory_limit = 2048M

But pool configuration enforces:

# /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = 512M

Result: Effective limit is 512M (pool wins).

Pool Configuration Directives

php_admin_value (Recommended)

Use this for critical limits. Application code cannot override with ini_set().

# /etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = 1024M
php_admin_value[max_execution_time] = 120
php_admin_value[upload_max_filesize] = 100M
php_admin_value[post_max_size] = 105M
php_admin_value[max_input_vars] = 5000

php_value (Less secure)

Application code CAN override these with ini_set(). Use only when dynamic adjustment is needed.

php_admin_flag / php_flag

For boolean settings (on/off):

php_admin_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_flag[expose_php] = off

Verifying Active Configuration

Quick Check:

# Create diagnostic page
echo '<?php phpinfo();' > /opt/dreamfactory/public/config-check.php
# Access: https://api.example.com/config-check.php
# Look for "Local Value" vs "Master Value" differences
# DELETE FILE IMMEDIATELY AFTER

Command Line:

# Check active settings
php -i | grep memory_limit
php -i | grep upload_max_filesize

# Find pool overrides
grep -E "php_(admin_)?(value|flag)" /etc/php/8.3/fpm/pool.d/www.conf

Inside DreamFactory Container:

docker compose exec web php artisan tinker
# Then run:
ini_get('memory_limit');
ini_get('upload_max_filesize');

Production Configuration Template

Recommended Approach: Pool Configuration as Source of Truth

php.ini (conservative baseline):

[PHP]
memory_limit = 256M
max_execution_time = 60
upload_max_filesize = 50M
post_max_size = 55M
max_input_vars = 5000
date.timezone = UTC

[opcache]
opcache.enable = 1
opcache.memory_consumption = 256
opcache.validate_timestamps = 0  # Production only

www.conf (production overrides):

[www]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock

# Process manager
pm = dynamic
pm.max_children = 80
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 2000

# Runtime limits (non-overridable)
php_admin_value[memory_limit] = 1024M
php_admin_value[max_execution_time] = 120
php_admin_value[upload_max_filesize] = 100M
php_admin_value[post_max_size] = 105M
php_admin_value[max_input_vars] = 5000

# Security
php_admin_flag[expose_php] = off
php_admin_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php8.3-fpm.log

# Timezone
php_admin_value[date.timezone] = UTC

# Session (Redis-backed)
php_value[session.save_handler] = redis
php_value[session.save_path] = "tcp://redis:6379"

# Monitoring
pm.status_path = /fpm-status

Nginx configuration:

server {
    listen 80;
    server_name api.example.com;
    root /opt/dreamfactory/public;

    client_max_body_size 100M;

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_read_timeout 180s;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

Common Pitfalls & Solutions

Pitfall 1: php.ini Changes Not Taking Effect

Symptom: Modified php.ini, restarted PHP-FPM, no change.

Cause: Pool configuration overriding php.ini.

Solution:

# Check pool overrides
grep "memory_limit" /etc/php/8.3/fpm/pool.d/www.conf
# Update pool config instead, then reload
systemctl reload php8.3-fpm

Pitfall 2: Forgot to Reload PHP-FPM

Symptom: Changed www.conf, no effect.

Solution:

# Graceful reload (no downtime)
systemctl reload php8.3-fpm

# Or in Docker
docker compose exec web kill -USR2 $(cat /var/run/php-fpm.pid)

Pitfall 3: Worker Pool Exhaustion

Symptom: "connect() to php-fpm.sock failed (Resource temporarily unavailable)"

Diagnosis:

# Check FPM status
curl http://localhost/fpm-status

# Look in logs
grep "pool www seems busy" /var/log/php8.3-fpm.log

Solution: Increase pm.max_children (ensure sufficient RAM).

Critical Monitoring Commands

# Real-time worker status
watch -n 1 'curl -s http://localhost/fpm-status'

# Check current worker count
ps aux | grep php-fpm | wc -l

# Monitor memory per worker
ps aux | grep php-fpm | awk '{print $6/1024 " MB"}'

# PHP-FPM logs
tail -f /var/log/php8.3-fpm.log

# DreamFactory application logs
tail -f /opt/dreamfactory/storage/logs/laravel.log

Quick Troubleshooting Workflow

When something isn't working:

  1. Check logs first:
    tail -f /var/log/php8.3-fpm.log
    tail -f /opt/dreamfactory/storage/logs/laravel.log
    
  2. Verify active config:
    php -i | grep -E "memory_limit|upload_max_filesize|max_execution_time"
    
  3. Check pool overrides:
    grep -E "php_(admin_)?(value|flag)" /etc/php/8.3/fpm/pool.d/www.conf
    
  4. Reload PHP-FPM:
    systemctl reload php8.3-fpm
    
  5. Test:
    • Retry failed operation
    • Check logs for new errors

Key Takeaways

  1. Pool configuration supersedes php.ini – Always check www.conf when settings don't work.
  2. pm.max_children is critical – Undersized pools cause cascading failures. Calculate based on RAM.
  3. Use php_admin_value – Prevents application code from bypassing limits.
  4. Match upload limits across stack – PHP settings must align with nginx/Apache limits.
  5. Monitor actively – Enable FPM status endpoint and watch logs for "pool busy" warnings.
  6. Reload after changes – PHP-FPM doesn't automatically reload configuration.

DreamFactory-Specific Recommendations

For typical production DreamFactory deployments:

  • memory_limit: 512M minimum (try to balance the lowest possible setting with your application demands)
  • pm.max_children: 80-100 for 8GB servers (scale with RAM)
  • upload_max_filesize: 100M standard (adjust for file service workloads)
  • max_execution_time: 120s (longer for schema introspection/ETL)
  • Use php_admin_value: Enforce limits at pool level
  • Enable Redis sessions: Better performance than file-based sessions
  • Monitor FPM status: Set up alerts for pool exhaustion

Additional Help

Please reach out to dspsupport@dreamfactory.com if you need additional help with php settings or configuration.

Resources:

Remember: Configuration must evolve with scale. What works at 10 requests/second fails at 100. Establish monitoring early and adjust based on real production metrics.