Senior & Lead Engineer
Interview Mastery Hub
100 real-world, scenario-based architecture & concurrency questions designed for 5–10+ years experienced developers. Free & open for every student and engineer.
100
Real-world Q&As
100%
Scenario-Based
5-10 Yrs
Senior / Lead Depth
5 Stacks
Core Technologies
Showing 20 questions for senior interview preparation
How does the Zend Engine manage memory with Zvals, Reference Counting, and the Circular Garbage Collector in PHP 8.x?
Zval Structure & Reference Counting
In PHP, variables are stored in a zval (Zend Value) struct containing:
value: Union storing the primitive or pointer.u1.type_info: Type identifier.refcount: Number of variables pointing to this compound value (arrays, objects).
The Circular Reference Trap
When Object A points to Object B, and Object B points to Object A:
$a = new Node();
$b = new Node();
$a->sibling = $b;
$b->sibling = $a;
unset($a, $b); // Refcounts decrement from 2 to 1, but never reach 0!
Even after unset(), both objects remain in memory because their refcount is 1.
Solving Daemon Memory Leaks
- PHP Cycle Collector Buffer: The GC buffer collects potential cyclic roots (10,000 max by default).
- Explicit Garbage Collection Trigger:
gc_collect_cycles(); // Forces cycle collection in loop gc_mem_caches(); // Releases cached memory chunks back to OS - Weak References (PHP 8.0+): Use
WeakReferenceso child nodes do not increment the parent's refcount:$this->parent = WeakReference::create($parentNode);
Explain PHP 8.4 Asymmetric Visibility, Property Hooks, and Constructor Property Promotion.
1. Asymmetric Visibility (PHP 8.4)
Allows a property to be publicly readable but privately or protectedly writable:
class User
{
public private(set) string $status = 'pending';
public function activate(): void
{
$this->status = 'active'; // Allowed inside class
}
}
$user = new User();
echo $user->status; // Allowed: readable
// $user->status = 'banned'; // FATAL ERROR: cannot modify private(set) property outside
2. Property Hooks (PHP 8.4)
Replaces repetitive getters and setters with direct property hooks:
class Product
{
public string $title;
public string $slug {
get => Str::slug($this->title);
}
public float $price {
set (float $value) {
if ($value < 0) throw new InvalidArgumentException("Price cannot be negative");
$this->price = round($value, 2);
}
}
}
How does the JIT (Just-In-Time) compiler in PHP 8.x work, and why does it benefit CPU-heavy tasks but not typical database-heavy web apps?
How PHP JIT Compiles Code
- Traditional PHP with OPcache: PHP source code is parsed into Abstract Syntax Tree (AST) -> Compiled into Opcodes -> Executed by the Zend VM bytecode interpreter.
- JIT (Tracing / Function JIT): Identifies frequently executed opcode paths ("hot spots") and translates those opcodes directly into raw machine code (x86_64 or ARM CPU instructions), bypassing Zend VM.
Why Web Apps See Minimal Gains
- Typical web applications are I/O-bound (waiting on MySQL network queries, Redis reads, filesystem, external HTTP calls).
- JIT accelerates CPU-bound mathematical computation, image rendering, 3D matrix math, and machine learning tokenization, where PHP spends 90%+ time in pure CPU instructions.
How do PHP Fibers work under the hood, and how do they differ from full async threads (Go Goroutines / Node.js Event Loop)?
Fibers: Full-Stack Stackful Coroutines
A Fiber in PHP 8.1+ represents an interruptible function with its own call stack:
- Can be paused (
Fiber::suspend()) and resumed ($fiber->resume()) from anywhere in the call hierarchy. - Cooperative Multitasking: Unlike OS threads, Fibers do NOT run in parallel across CPU cores. They yield execution cooperatively.
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('paused state');
echo "Resumed with: {$value}\n";
});
$result = $fiber->start(); // Returns 'paused state'
$fiber->resume('new value'); // Outputs: Resumed with: new value
Framework Ecosystem
Fibers provide low-level primitives utilized by async engines like Revolt, Amphp v3, and ReactPHP to eliminate "callback hell" while keeping synchronous-looking code.
How do you stream and parse a 50GB JSON/CSV export file in PHP without exceeding a 128MB memory limit?
Solution: PHP Generators (yield) & Stream Contexts
function streamCsvRows(string $filePath): \Generator
{
$handle = fopen($filePath, 'r');
if (! $handle) {
throw new RuntimeException("Cannot open file");
}
try {
while (($row = fgetcsv($handle, 4096)) !== false) {
yield $row;
}
} finally {
fclose($handle);
}
}
// Processing 50GB file using under 5MB of constant RAM
foreach (streamCsvRows('large_dataset.csv') as $row) {
processRow($row);
}
yield retains only a single record in RAM at any given millisecond.
How does OPcache Preloading work in PHP 8.x, and how do you configure it in containerized production environments?
OPcache Preloading Mechanics
When PHP-FPM starts up, a designated preload script compiles specified classes, traits, and interfaces directly into permanent shared memory before any HTTP request is accepted:
opcache.preload=/var/www/preload.php
opcache.preload_user=www-data
Considerations & Gotchas
- Preloaded classes are permanently bound in memory.
- If code changes on disk, you must restart PHP-FPM (
systemctl restart php-fpm) for preloaded memory to reload. - Preload only stable framework code (e.g.
vendor/and core service classes), not dynamically changing code.
Explain Reflection vs. Attributes in PHP 8.x and how to build high-performance metadata routers.
Creating & Reading Native Attributes
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
class Route
{
public function __construct(
public string $path,
public string $method = 'GET'
) {}
}
class UserController
{
#[Route('/api/v1/users', method: 'GET')]
public function list(): JsonResponse { ... }
}
// Reading via Reflection
$reflection = new ReflectionMethod(UserController::class, 'list');
$attributes = $reflection->getAttributes(Route::class);
foreach ($attributes as $attr) {
$routeInstance = $attr->newInstance();
echo $routeInstance->path; // '/api/v1/users'
}
Native attributes are parsed at compile time, eliminating regex docblock string parsing.
How do you handle Deadlocks and Race Conditions in file-based locks (`flock`) across multi-process PHP scripts?
Non-Blocking File Locking Pattern
$fp = fopen('/tmp/cron_task.lock', 'c+');
// LOCK_EX (Exclusive lock) | LOCK_NB (Non-blocking: fail immediately if locked)
if (! flock($fp, LOCK_EX | LOCK_NB)) {
echo "Another process is already executing this task. Exiting.\n";
fclose($fp);
exit(0);
}
try {
// Critical section execution
executeHeavyBatchJob();
} finally {
flock($fp, LOCK_UN); // Release lock
fclose($fp);
}
How does Type Juggling and Strict Typing (`declare(strict_types=1);`) affect function returns, arrays, and coercion in PHP 8.x?
File-Level Scope of strict_types
declare(strict_types=1); is per-file and affects function calls made FROM that specific file, not the file declaring the function.
- If File A has
strict_types=1and callscalculateTax("100.50"), PHP throwsTypeError. - If File B does NOT have
strict_types=1and calls the samecalculateTax("100.50"), PHP coerces the string to float100.50. - Best practice: Enforce
declare(strict_types=1);across all project files via code standards tools (PHP-CS-Fixer / Pint).
How do you profile PHP performance bottlenecks, CPU cycles, and memory consumption using Blackfire, Xhprof, and SPX?
Profiling Methodology
- Instrument with SPX / Xhprof: Generates a Call Graph tracking:
- Wall time vs CPU time
- Memory peak allocations per function call
- Function invocation count
- Common Culprits:
- Deep nested loops hydrating arrays into domain objects.
- Repetitive serialization / JSON parsing.
- Autoloader filesystem IO when APCu/OPcache is misconfigured.
Explain the difference between `Pdo` connection pooling vs persistent connections (`PDO::ATTR_PERSISTENT`) in PHP-FPM.
The Persistent Connection Danger in PHP-FPM
With PDO::ATTR_PERSISTENT, each PHP-FPM worker process keeps its own persistent database connection open even after the request terminates.
- If you have 500 PHP-FPM workers across 4 web servers, that equals 2,000 persistent idle database connections.
- Solution: Use dedicated external connection poolers (like ProxySQL for MySQL or PgBouncer for PostgreSQL) rather than in-process persistent PDO connections.
How does the Match Expression differ internally from the Switch Statement in PHP 8.x?
match vs switch Differences
- Strict Comparison:
matchuses===identity matching;switchuses loose==comparison. - Returns a Value:
matchis an expression that evaluates directly to a result. - No Fallthrough:
matchdoes not requirebreak;statements. - Exhaustive Matching: Throws
UnhandledMatchErrorif no branch matches and nodefaultis specified.
How do Enums in PHP 8.1+ support Backed Values, Methods, and Interfaces?
Backed Enum with Methods & Traits
enum OrderStatus: string implements HasLabel
{
case PENDING = 'pending';
case PROCESSING = 'processing';
case COMPLETED = 'completed';
case CANCELLED = 'cancelled';
public function label(): string
{
return match($this) {
self::PENDING => 'Awaiting Payment',
self::PROCESSING => 'In Progress',
self::COMPLETED => 'Order Delivered',
self::CANCELLED => 'Order Cancelled',
};
}
public function canCancel(): bool
{
return in_array($this, [self::PENDING, self::PROCESSING], true);
}
}
How do you implement and verify Cryptographic Signatures (HMAC-SHA256) with timing attack prevention in PHP?
Timing Attacks & Constant-Time String Comparison
Standard string comparisons (===) fail fast at the first differing byte. An attacker measuring millisecond response timing can deduce character by character.
$computedSignature = hash_hmac('sha256', $rawPayload, $secretKey);
// VULNERABLE to timing attacks:
// if ($computedSignature === $incomingSignature) { ... }
// SECURE constant-time verification:
if (! hash_equals($computedSignature, $incomingSignature)) {
throw new SecurityException("Invalid webhook signature.");
}
How do you design a High-Performance In-Memory Cache using Shared Memory (`shmop` / APCu) in PHP without Redis?
APCu Direct RAM Access
APCu stores PHP variables directly in the web server process shared memory, avoiding TCP network roundtrips to Redis:
if (! apcu_exists('global_config')) {
$config = loadHeavyConfig();
apcu_store('global_config', $config, 3600);
} else {
$config = apcu_fetch('global_config');
}
Latency is under 5 microseconds, compared to 0.5-2ms for Redis over TCP.
Explain Late Static Binding (`static::` vs `self::`) in complex class inheritance hierarchies.
Late Static Binding
self::resolves to the class where the method is written.static::resolves to the class that was actually called at runtime.
class Model {
public static function create(): static {
return new static(); // Returns instance of User when called as User::create()
}
}
class User extends Model {}
$user = User::create(); // Instance of User
How do you handle Unhandled Exceptions and Fatal Errors gracefully in PHP 8 with custom error handlers?
Handling \Throwable (Exception + Error)
In PHP 7+, all exceptions and fatal runtime errors implement \Throwable:
set_exception_handler(function (\Throwable $e) {
Log::error($e->getMessage(), ['trace' => $e->getTraceAsString()]);
http_response_code(500);
header('Content-Type: application/json');
echo json_encode([
'error' => 'Internal Server Error',
'code' => 500,
]);
exit;
});
Explain the differences between Deep Copy vs Shallow Copy with PHP `clone` and `__clone()`.
Shallow vs Deep Clone
Standard $b = clone $a copies primitive properties by value, but nested objects remain references to the original instance.
class Invoice
{
public Customer $customer;
public function __clone()
{
// Deep copy nested object
$this->customer = clone $this->customer;
}
}
How do you optimize PHP-FPM `pm = dynamic` vs `pm = static` for high-concurrency servers?
Calculating Optimal pm = static Configuration
On dedicated production servers, pm = static avoids the CPU overhead of constantly spawning and destroying worker processes.
Formula:
max_children = (Total RAM - OS/Services RAM) / Average Worker Memory (e.g. 50MB)
Example: (60,000 MB) / 50 MB = 1200 workers
pm = static
pm.max_children = 1200
pm.max_requests = 1000 ; Recycles workers to prevent slow memory leaks
How do Readonly Classes in PHP 8.2+ enforce immutability in Domain-Driven Design (DDD) Data Transfer Objects (DTOs)?
PHP 8.2 Readonly Classes
Marking a class readonly automatically enforces that all declared properties are readonly and prevents dynamic property creation:
readonly class TransferLedgerDTO
{
public function __construct(
public string $transactionId,
public int $amountCents,
public string $currency,
public DateTimeImmutable $timestamp
) {}
}