php runtime and server environment
Development Parity With Production
Development parity means the local environment is close enough to production that important bugs can be reproduced before deployment. It does not mean local and production are identical. It means the differences are known, deliberate, and unlikely to hide real runtime problems.
For PHP projects, parity starts with PHP version, extensions, php.ini, web server routing, database/cache versions, queues, scheduled tasks, and environment variables.
A small parity check
<?php
declare(strict_types=1);
$expected = [
'PHP_MAJOR_MINOR' => '8.3',
'memory_limit' => '128M',
];
$actual = [
'PHP_MAJOR_MINOR' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
'memory_limit' => ini_get('memory_limit'),
];
foreach ($expected as $name => $requiredValue) {
$currentValue = $actual[$name];
$status = $currentValue === $requiredValue ? 'OK' : 'DIFFERS';
echo "{$name}: {$currentValue} ({$status})" . PHP_EOL;
}
// Prints:
// PHP_MAJOR_MINOR: 8.3 (OK)
// memory_limit: 128M (OK)
This kind of check is not a replacement for documentation, but it makes hidden runtime differences visible.
What should match closely
These differences commonly cause bugs:
- PHP major/minor version
- required PHP extensions
- important
php.inivalues such as memory, uploads, timezones, and OPcache behaviour - database engine and major version
- Redis or cache availability
- queue worker behaviour
- scheduled task behaviour
- filesystem paths and writable directories
- web server document root and rewrite rules
- environment variable names and required values
If production uses PHP-FPM behind Nginx but local uses only php -S, some routing, upload, header, and FastCGI issues may not appear locally.
What can differ deliberately
Some differences are normal:
- local debug mode can be enabled
- Xdebug can exist locally but not in production
- local passwords can be fake
- local services can use smaller datasets
- local mail can go to a mail-catcher
- local logs can be more verbose
The difference should be documented and understood. Undocumented differences are where surprises come from.
Parity review questions
Ask these during onboarding or before blaming application code:
- Which PHP version runs locally, in CI, and in production?
- Are required extensions loaded in all three places?
- Does local use the same public document root shape as production?
- Are queues and scheduled tasks running locally when the feature depends on them?
- Are database/cache versions close enough to catch real behaviour?
- Are environment variables documented with safe local examples?
- Are long-running workers restarted during deploys?
What you should be able to do
After this lesson, you should be able to explain development parity, identify runtime differences that can hide bugs, write a small parity diagnostic, and decide which differences are acceptable local conveniences versus dangerous mismatches.
Practice
Task: Write A Parity Checklist
Create a small PHP diagnostic or checklist that compares local runtime expectations with the current environment.
Requirements
- Check PHP major/minor version.
- Check at least three required extensions.
- Check one important
php.inivalue. - Include queue, database, cache, and web server routing in the written checklist.
- Add a short note explaining which local differences are acceptable and which are risky.
Check your work
The result should help a developer spot environment drift before assuming a bug is in application code.
Show solution
<?php
declare(strict_types=1);
$expectedPhp = '8.3';
$actualPhp = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION;
echo 'PHP: ' . $actualPhp . ($actualPhp === $expectedPhp ? ' OK' : ' DIFFERS') . PHP_EOL;
foreach (['pdo', 'mbstring', 'openssl'] as $extension) {
echo $extension . ': ' . (extension_loaded($extension) ? 'loaded' : 'missing') . PHP_EOL;
}
echo 'memory_limit: ' . ini_get('memory_limit') . PHP_EOL;
// Prints:
// PHP: 8.3 OK
// pdo: loaded
// mbstring: loaded
// openssl: loaded
// memory_limit: 128M
Checklist:
- Confirm local, CI, and production use the expected PHP major/minor version.
- Confirm required extensions are loaded in the runtime that handles the app.
- Confirm important php.ini settings such as memory, uploads, timezone, and OPcache.
- Confirm local database and cache services are close enough to production behaviour.
- Confirm queue workers and scheduled tasks run locally when the feature needs them.
- Confirm the local web server uses the same public document root and routing shape.
Acceptable local differences include Xdebug, fake passwords, local mail capture, and smaller datasets. Risky differences include missing extensions, different PHP versions, different document roots, disabled queues, and services replaced with mocks when the feature depends on real service behaviour.