November 2, 2026
How to Protect Apache and Laravel Applications from DDoS Attacks in 2026: Complete Production…
A practical guide to securing Apache HTTP Server, Laravel, PHP-FPM, PostgreSQL, and Linux infrastructure against DDoS attacks, HTTP floods…

By Vikash Kumar Gupta
22 min read
A practical guide to securing Apache HTTP Server, Laravel, PHP-FPM, PostgreSQL, and Linux infrastructure against DDoS attacks, HTTP floods, malicious bots, and application-layer resource exhaustion.
Introduction
Imagine you are managing a production Laravel application used by thousands of people every day.
The application handles user authentication, online payments, API requests, report generation, file uploads, and database transactions.
Everything is working normally until suddenly the website becomes extremely slow.
Pages that previously loaded within two seconds now take 20–30 seconds. Some users receive 503 Service Unavailable, while others encounter 504 Gateway Timeout.
You check the Linux server and observe that Apache workers are busy, PHP-FPM processes are increasing, and incoming requests are unusually high.
However, CPU utilization remains relatively low, and the server still has available RAM.
What is happening?
The issue could be a Distributed Denial-of-Service (DDoS) attack, a malicious HTTP request flood, an inefficient application endpoint, or a combination of these problems.
In 2026, DDoS protection is no longer just about blocking suspicious IP addresses. Modern attackers can generate large volumes of traffic using botnets, distributed proxy networks, automated scripts, and cloud infrastructure.
Traditional firewall rules alone are not enough to protect complex web applications.
A reliable defense requires multiple layers of protection:
- Network-level DDoS mitigation
- Web Application Firewall (WAF)
- Apache HTTP Server optimization
- PHP-FPM worker management
- Laravel rate limiting
- PostgreSQL query optimization
- Linux firewall configuration
- Redis caching and request throttling
- Real-time monitoring and alerting
- Incident response and recovery planning
This guide explains how these components work together and how to configure them safely in production environments.
1. What Is a DDoS Attack?
A Distributed Denial-of-Service (DDoS) attack is an attempt to make a website, application, or network service unavailable by overwhelming it with excessive traffic or requests from multiple sources.
Unlike a conventional security attack that attempts to steal information or compromise an application, a DDoS attack primarily targets availability.
A successful DDoS attack can prevent legitimate users from accessing a service without the attacker gaining access to the database or application code.
How a DDoS Attack Works
Consider a normal Laravel application:
- A user sends an HTTP request.
- Apache receives the request.
- Apache forwards PHP requests to PHP-FPM.
- PHP-FPM executes the Laravel application.
- Laravel performs database queries or other operations.
- The server returns the response.
Under normal traffic conditions, requests are processed within the infrastructure's available capacity.
During an application-layer DDoS attack, thousands of requests may arrive within a short period.
Each request can consume resources such as:
- Apache worker capacity
- PHP-FPM processes
- CPU processing time
- Memory
- Database connections
- Network bandwidth
- File descriptors
- Application cache capacity
Eventually, the infrastructure may be unable to process legitimate requests.
Main Types of DDoS Attacks
1. Volumetric Attacks
These attacks attempt to saturate the available network bandwidth.
Examples include UDP floods and amplification attacks.
If a server has a 1 Gbps internet connection and receives traffic exceeding its available upstream capacity, legitimate traffic may be delayed or dropped before it reaches Apache.
2. Protocol Attacks
These attacks target network protocols or connection-handling resources.
Examples include SYN floods and connection-state exhaustion.
3. Application-Layer Attacks
These attacks target HTTP or HTTPS services.
Examples include:
- HTTP GET floods
- HTTP POST floods
- Repeated login requests
- Excessive API requests
- Automated report generation
- Expensive database query requests
- Slow HTTP requests
Application-layer attacks are especially challenging because malicious requests can resemble legitimate user activity.
2. Why Apache and Laravel Applications Become Slow During Attacks
A typical production architecture may look like this:
INTERNET
|
v
CDN / WAF / Firewall
|
v
Apache HTTP Server
|
v
PHP-FPM
|
v
Laravel Application
|
----------------
| |
v v
PostgreSQL Redis
|
v
Application Data INTERNET
|
v
CDN / WAF / Firewall
|
v
Apache HTTP Server
|
v
PHP-FPM
|
v
Laravel Application
|
----------------
| |
v v
PostgreSQL Redis
|
v
Application DataEach component has a finite capacity.
For example, Apache can accept a large number of HTTP connections, but the PHP-FPM pool may support far fewer simultaneously executing PHP requests.
Suppose PHP-FPM has 100 available workers.
If 100 requests each take 20 seconds to complete, every worker may remain occupied.
New requests must wait in a queue.
As waiting times increase, users experience slow pages and eventually timeouts.
Why More RAM and CPU May Not Fix the Problem
Imagine a server with:
- 48 CPU cores
- 128 GB RAM
- Apache Event MPM
- PHP-FPM
- Laravel
- PostgreSQL
Even with these resources, the application can become unavailable.
Why?
Because the bottleneck may not be CPU or RAM.
PHP processes could be waiting for slow database queries, external API responses, file operations, or locks.
For example:
CPU Utilization: 12%
Available RAM: 75 GB
PHP-FPM Active Workers: 120/120
Apache Busy Workers: 950/1024
HTTP 503 Errors: IncreasingCPU Utilization: 12%
Available RAM: 75 GB
PHP-FPM Active Workers: 120/120
Apache Busy Workers: 950/1024
HTTP 503 Errors: IncreasingThis is an illustrative scenario.
The application is overloaded despite having spare CPU and RAM because request-processing capacity is exhausted.
Key lesson: Application performance depends on the entire request-processing pipeline, not just hardware resources.
3. How to Identify a Possible DDoS Attack
Before blocking traffic, determine whether the problem is actually malicious.
High traffic can also result from legitimate demand, inefficient SQL queries, faulty client integrations, or background processes.
Common warning signs include:
- A sudden increase in requests per second.
- Repeated requests to the same endpoint.
- Unusual traffic from many IP addresses.
- A sharp increase in HTTP 403, 429, 503, or 504 responses.
- Apache worker saturation.
- PHP-FPM reaching
pm.max_children. - Increasing database connections.
- High incoming network bandwidth.
- Repeated requests to expensive endpoints.
- Significant increases in response times.
A single symptom is not enough to confirm a DDoS attack.
Correlate Apache logs, PHP-FPM metrics, Laravel logs, database activity, and network statistics.
4. Check Linux Server Performance
When a production application becomes slow, start by checking server health.
Check Uptime and Load Average
uptimeuptimeExample:
15:30:20 up 12 days, 4:20,
load average: 8.50, 7.20, 6.9015:30:20 up 12 days, 4:20,
load average: 8.50, 7.20, 6.90The three load-average values represent approximately 1, 5, and 15 minutes.
Load average includes runnable tasks and tasks waiting in uninterruptible sleep.
A load average of 8 on a 48-core server is not automatically a sign of overload.
Check CPU Utilization
toptopPress 1 to view per-CPU utilization.
For a quick snapshot:
top -b -n1 | head -30top -b -n1 | head -30Check Memory
free -hfree -hExample:
total used free buff/cache available
Mem: 128Gi 15Gi 20Gi 93Gi 105Gi total used free buff/cache available
Mem: 128Gi 15Gi 20Gi 93Gi 105GiHigh buff/cache utilization is normal on Linux because unused memory is used for filesystem caching.
Focus on available memory, swapping, memory pressure, and process behavior.
Check TCP Connection Statistics
ss -sss -sCheck established HTTPS connections:
ss -tan state established '( sport = :443 )'ss -tan state established '( sport = :443 )'Count them:
ss -Htan state established '( sport = :443 )' | wc -lss -Htan state established '( sport = :443 )' | wc -lA large number of established connections may indicate heavy traffic, but does not prove malicious activity.
5. Analyze Apache Access Logs
Apache access logs are essential for identifying unusual request patterns.
On many RHEL-based systems, logs are located in:
/var/log/httpd//var/log/httpd/View available logs:
ls -lh /var/log/httpd/ls -lh /var/log/httpd/Monitor incoming requests:
sudo tail -f /var/log/httpd/access_logsudo tail -f /var/log/httpd/access_logIdentify Top Requesting IP Addresses
For a standard Apache combined access-log format:
sudo awk '{print $1}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nr \
| head -20sudo awk '{print $1}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nr \
| head -20Example:
15000 192.0.2.10
12000 198.51.100.20
8500 203.0.113.1515000 192.0.2.10
12000 198.51.100.20
8500 203.0.113.15These are documentation-only IP addresses.
High request counts should be investigated before blocking because corporate networks, NAT gateways, and legitimate integrations can produce substantial traffic.
Identify Frequently Requested URLs
sudo awk '{print $7}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nr \
| head -20sudo awk '{print $7}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nr \
| head -20Example:
20000 /login
15000 /api/send-otp
12000 /api/search
8000 /dashboard20000 /login
15000 /api/send-otp
12000 /api/search
8000 /dashboardRepeated requests to expensive endpoints can indicate automated abuse.
Analyze HTTP Status Codes
sudo awk '{print $9}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nrsudo awk '{print $9}' /var/log/httpd/access_log \
| sort \
| uniq -c \
| sort -nrExample:
85000 200
15000 403
12000 429
8000 503
2500 50485000 200
15000 403
12000 429
8000 503
2500 504These codes provide useful clues:
- 200: Request completed successfully.
- 403: Access forbidden.
- 429: Too many requests.
- 503: Service temporarily unavailable.
- 504: Gateway timeout.
Analyze Traffic by Minute
For a standard combined log format:
sudo awk '{print $4}' /var/log/httpd/access_log \
| cut -c 2-18 \
| sort \
| uniq -c \
| sort -nr \
| head -20sudo awk '{print $4}' /var/log/httpd/access_log \
| cut -c 2-18 \
| sort \
| uniq -c \
| sort -nr \
| head -20This helps identify minutes with unusually high request volumes.
For reliable production analysis, use structured logs and centralized analytics, especially when Apache is behind a CDN or reverse proxy.
6. Configure Apache Event MPM
Apache HTTP Server supports different Multi-Processing Modules:
- Prefork MPM
- Worker MPM
- Event MPM
For modern Laravel deployments using PHP-FPM, Event MPM is generally a strong option.
Event MPM improves connection handling by allowing idle keep-alive connections to be managed more efficiently.
Check Active MPM
httpd -V | grep -i mpmhttpd -V | grep -i mpmOr:
apachectl -M | grep mpmapachectl -M | grep mpmExpected output:
mpm_event_module (shared)mpm_event_module (shared)Example Event MPM Configuration
<IfModule mpm_event_module>
ServerLimit 16
StartServers 4
ThreadsPerChild 64
ThreadLimit 64
MaxRequestWorkers 1024
MinSpareThreads 128
MaxSpareThreads 512
MaxConnectionsPerChild 10000
</IfModule><IfModule mpm_event_module>
ServerLimit 16
StartServers 4
ThreadsPerChild 64
ThreadLimit 64
MaxRequestWorkers 1024
MinSpareThreads 128
MaxSpareThreads 512
MaxConnectionsPerChild 10000
</IfModule>This example permits up to 1,024 worker threads across 16 child processes.
These values are illustrative and should not be copied directly into production without capacity testing.
Understanding Important Directives
ServerLimit
Controls the maximum number of child process slots.
StartServers
Specifies the number of Apache child processes started initially.
ThreadsPerChild
Defines the number of worker threads per child process.
MaxRequestWorkers
Limits the number of simultaneous requests Apache can actively process through its worker threads.
MinSpareThreads
Specifies the minimum number of idle worker threads Apache attempts to maintain.
MaxSpareThreads
Specifies the maximum number of idle worker threads.
MaxConnectionsPerChild
Controls how many connections a child process handles before recycling.
Why Incorrect Apache Configuration Causes Problems
If MaxRequestWorkers is too low, legitimate requests may wait unnecessarily.
If it is too high, Apache may consume excessive resources or overwhelm PHP-FPM and PostgreSQL.
Increasing worker capacity without measuring backend capacity can make application performance worse.
The correct configuration depends on:
- Available RAM
- CPU capacity
- Average request duration
- PHP-FPM capacity
- Database connection limits
- Traffic patterns
- Reverse-proxy architecture
Validate Configuration
sudo apachectl configtestsudo apachectl configtestExpected:
Syntax OKSyntax OKReload:
sudo systemctl reload httpdsudo systemctl reload httpdSome startup-only MPM settings require a full restart to take effect.
Always plan configuration changes and maintain a rollback procedure.
7. Configure Apache KeepAlive and Timeouts
Apache KeepAlive allows multiple HTTP requests to reuse an existing TCP connection.
This reduces connection establishment overhead.
However, excessively long idle connections can consume resources.
Example:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2
Timeout 60KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2
Timeout 60Explanation
The Apache Timeout directive is not a universal maximum execution time for Laravel requests.
PHP-FPM, reverse proxies, database operations, and external APIs may have independent timeout settings.
Protect Against Slow HTTP Requests
Apache provides mod_reqtimeout to limit how slowly clients can send HTTP request headers and bodies.
Check whether it is enabled:
httpd -M | grep reqtimeouthttpd -M | grep reqtimeoutExample:
<IfModule reqtimeout_module>
RequestReadTimeout header=10-20,MinRate=500 body=20,MinRate=500
</IfModule><IfModule reqtimeout_module>
RequestReadTimeout header=10-20,MinRate=500 body=20,MinRate=500
</IfModule>This can help mitigate slow HTTP request attacks.
Test these settings carefully with legitimate mobile users, slower networks, and file uploads.
8. Install and Configure ModSecurity WAF
A Web Application Firewall inspects incoming HTTP traffic and applies security rules.
ModSecurity is a commonly used open-source WAF engine for Apache environments.
It can help detect suspicious requests, known web attacks, and certain abusive patterns.
However, it cannot independently protect against every DDoS attack.
Check Package Availability
sudo dnf search mod_securitysudo dnf search mod_securityWhere supported:
sudo dnf install mod_securitysudo dnf install mod_securityPackage names and availability depend on the operating system and configured repositories.
Verify Installation
httpd -M | grep securityhttpd -M | grep securityExample ModSecurity Configuration
SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRequestBodyLimit 10485760SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecResponseBodyAccess Off
SecRequestBodyLimit 10485760Start with detection mode to observe how rules affect legitimate requests.
After tuning and testing:
SecRuleEngine OnSecRuleEngine OnUse a maintained OWASP Core Rule Set compatible with the installed ModSecurity version.
Why Detection Mode Matters
A WAF can accidentally block legitimate requests.
For example:
- Large JSON payloads
- Complex search filters
- File uploads
- API requests
- Payment callback requests
- Form submissions containing special characters
Before enabling blocking, verify that critical application functions continue to work.
9. Implement Laravel Rate Limiting
Laravel provides built-in rate limiting to restrict how frequently clients can access specific endpoints.
This is especially important for:
- Login
- OTP generation
- Search APIs
- Report downloads
- Expensive database queries
- File generation
- Public API endpoints
Define a Rate Limiter
For Laravel 10, define the limiter in the appropriate service provider, commonly RouteServiceProvider.
For newer Laravel application structures, it can be registered in AppServiceProvider.
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('api-security', function (Request $request) {
return Limit::perMinute(60)
->by(
$request->user()?->getAuthIdentifier()
?: $request->ip()
);
});use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('api-security', function (Request $request) {
return Limit::perMinute(60)
->by(
$request->user()?->getAuthIdentifier()
?: $request->ip()
);
});This example allows up to 60 requests per minute per authenticated user or client IP.
Apply Rate Limiting to Routes
Route::middleware(['throttle:api-security'])
->group(function () {
Route::get('/project-list', [
ProjectController::class,
'index'
]);
Route::get('/report', [
ReportController::class,
'index'
]);
});Route::middleware(['throttle:api-security'])
->group(function () {
Route::get('/project-list', [
ProjectController::class,
'index'
]);
Route::get('/report', [
ReportController::class,
'index'
]);
});When a client exceeds the configured limit, Laravel returns HTTP 429.
Protect OTP APIs
OTP endpoints can be abused because they may trigger SMS delivery and database writes.
RateLimiter::for('send-otp', function (Request $request) {
$mobile = preg_replace(
'/\D+/',
'',
(string) $request->input('mobile')
);
return [
Limit::perMinute(5)
->by('otp-ip:'.$request->ip()),
Limit::perMinute(3)
->by('otp-mobile:'.hash('sha256', $mobile))
];
});RateLimiter::for('send-otp', function (Request $request) {
$mobile = preg_replace(
'/\D+/',
'',
(string) $request->input('mobile')
);
return [
Limit::perMinute(5)
->by('otp-ip:'.$request->ip()),
Limit::perMinute(3)
->by('otp-mobile:'.hash('sha256', $mobile))
];
});Apply it:
Route::post('/send-otp', [
AuthController::class,
'sendOtp'
])->middleware('throttle:send-otp');Route::post('/send-otp', [
AuthController::class,
'sendOtp'
])->middleware('throttle:send-otp');Validate phone numbers and normalize them to a consistent format before constructing limiter keys.
A phone-number limit can also be abused to deny service to another user, so combine it with cooldowns, per-account controls, and appropriate anti-automation mechanisms.
Why Laravel Rate Limiting Alone Is Not Enough
Laravel rate limiting operates after the request reaches the application stack.
This means Apache and PHP-FPM may already have spent resources processing the request.
Therefore, edge-level or reverse-proxy rate limiting should complement Laravel middleware.
10. Use Redis for Rate Limiting and Caching
Redis is useful for shared rate limiting, caching, session storage, and queue management.
In a multi-server Laravel environment, a shared rate-limit store prevents each application instance from maintaining independent counters.
Example Laravel configuration:
CACHE_STORE=redis
REDIS_CLIENT=phpredisCACHE_STORE=redis
REDIS_CLIENT=phpredisFor Laravel 10, verify whether the application's configuration uses CACHE_DRIVER instead of CACHE_STORE.
Benefits of Redis
Redis can reduce repeated database queries and support fast, centralized rate-limit counters.
It can also improve performance when caching data that is expensive to calculate.
However, Redis must be monitored and secured.
Do not expose Redis publicly.
Configure appropriate memory limits, authentication or network access controls, and eviction policies.
Example Laravel Cache Usage
use Illuminate\Support\Facades\Cache;
$summary = Cache::remember(
'dashboard_summary',
now()->addMinutes(5),
function () {
return DB::table('rawaana_details')
->selectRaw('COUNT(*) AS total')
->first();
}
);use Illuminate\Support\Facades\Cache;
$summary = Cache::remember(
'dashboard_summary',
now()->addMinutes(5),
function () {
return DB::table('rawaana_details')
->selectRaw('COUNT(*) AS total')
->first();
}
);This example caches an aggregate query for five minutes.
The appropriate cache duration depends on how frequently the underlying data changes and how fresh the application response must be.
11. Configure PHP-FPM for High Traffic
PHP-FPM manages PHP worker processes.
Each active PHP request consumes a worker until execution completes or terminates.
If every worker becomes busy, additional requests may wait in a queue.
Check PHP-FPM Service
sudo systemctl status php-fpmsudo systemctl status php-fpmCheck PHP-FPM Logs
sudo journalctl -u php-fpm --since "30 minutes ago"sudo journalctl -u php-fpm --since "30 minutes ago"Common warning:
server reached pm.max_children settingserver reached pm.max_children settingThis indicates that the configured maximum number of child processes has been reached.
Example PHP-FPM Configuration
A common configuration path is:
/etc/php-fpm.d/www.conf/etc/php-fpm.d/www.confExample:
pm = dynamic
pm.max_children = 120
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 40
pm.max_requests = 1000
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
request_terminate_timeout = 120spm = dynamic
pm.max_children = 120
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 40
pm.max_requests = 1000
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.log
request_terminate_timeout = 120sThese values are examples only.
Understanding PHP-FPM Settings
pm.max_children
Maximum number of child processes in the pool.
pm.start_servers
Number of child processes created at startup when using dynamic process management.
pm.min_spare_servers
Minimum number of idle workers.
pm.max_spare_servers
Maximum number of idle workers.
pm.max_requests
Number of requests a worker handles before recycling.
request_slowlog_timeout
Duration after which PHP-FPM records a stack trace for a slow request.
request_terminate_timeout
A limit on request execution time enforced by PHP-FPM, subject to its documented behavior and configuration.
Calculate PHP-FPM Capacity
A simplified formula:
Maximum Workers =
PHP-FPM Memory Budget / Average Memory per Busy WorkerMaximum Workers =
PHP-FPM Memory Budget / Average Memory per Busy WorkerExample:
PHP-FPM Memory Budget: 24 GB
Memory per Busy Worker: 150 MB
Maximum Workers = 24576 / 150
Maximum Workers ≈ 163PHP-FPM Memory Budget: 24 GB
Memory per Busy Worker: 150 MB
Maximum Workers = 24576 / 150
Maximum Workers ≈ 163This provides a memory-based estimate, not a guaranteed safe production limit.
The real worker limit may need to be lower because of database connections, CPU utilization, external APIs, and other bottlenecks.
Increasing pm.max_children without evaluating these dependencies may worsen overall performance.
12. Enable PHP-FPM Slow Logging
PHP-FPM slow logs help identify requests that take too long to execute.
Example:
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.logrequest_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/www-slow.logValidate configuration:
sudo php-fpm -tsudo php-fpm -tRestart PHP-FPM through an approved deployment procedure:
sudo systemctl restart php-fpmsudo systemctl restart php-fpmInspect logs:
sudo tail -f /var/log/php-fpm/www-slow.logsudo tail -f /var/log/php-fpm/www-slow.logExample:
script_filename = /var/www/html/laravel/public/index.php
Illuminate\Database\Connection->select()
Illuminate\Database\Connection->run()
App\Http\Controllers\ReportController->index()script_filename = /var/www/html/laravel/public/index.php
Illuminate\Database\Connection->select()
Illuminate\Database\Connection->run()
App\Http\Controllers\ReportController->index()This indicates that a request was executing a database operation when the slow-log snapshot was captured.
It does not identify the full SQL query by itself.
Correlate the request with Laravel query logs, application tracing, and PostgreSQL monitoring.
Enable PHP-FPM Status
In the pool configuration:
pm.status_path = /fpm-statuspm.status_path = /fpm-statusConfigure the web server to expose this endpoint only to trusted monitoring systems.
Never expose PHP-FPM status publicly.
Useful metrics include:
- Active processes
- Idle processes
- Listen queue
- Maximum listen queue
- Max children reached
- Slow requests
13. Optimize PostgreSQL for High-Concurrency Applications
A large HTTP request flood can become a database overload when each request executes SQL queries.
Even if PostgreSQL has sufficient CPU and memory, expensive queries and connection contention can slow the entire application.
Identify Active Slow Queries
SELECT
pid,
now() - query_start AS duration,
state,
wait_event_type,
wait_event,
LEFT(query, 1500) AS query
FROM pg_stat_activity
WHERE state = 'active'
AND pid <> pg_backend_pid()
AND now() - query_start > INTERVAL '5 seconds'
ORDER BY duration DESC;SELECT
pid,
now() - query_start AS duration,
state,
wait_event_type,
wait_event,
LEFT(query, 1500) AS query
FROM pg_stat_activity
WHERE state = 'active'
AND pid <> pg_backend_pid()
AND now() - query_start > INTERVAL '5 seconds'
ORDER BY duration DESC;This query displays active SQL statements running for more than five seconds.
If no rows are returned, no matching statement was active at the time of sampling.
It does not mean the database has never experienced slow queries.
Enable Slow Query Logging
In PostgreSQL configuration:
log_min_duration_statement = 5000log_min_duration_statement = 5000This logs statements taking at least five seconds.
Reload PostgreSQL configuration:
SELECT pg_reload_conf();SELECT pg_reload_conf();Protect access to database logs because SQL statements may contain sensitive information.
Monitor Connection Counts
SELECT
state,
COUNT(*)
FROM pg_stat_activity
GROUP BY state;SELECT
state,
COUNT(*)
FROM pg_stat_activity
GROUP BY state;Check Long-Running Transactions
SELECT
pid,
usename,
state,
now() - xact_start AS transaction_age,
LEFT(query, 200) AS query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY transaction_age DESC;SELECT
pid,
usename,
state,
now() - xact_start AS transaction_age,
LEFT(query, 200) AS query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY transaction_age DESC;Long-running transactions can retain locks and interfere with database maintenance.
Use pg_stat_statements
Where the extension is enabled:
SELECT
calls,
ROUND(total_exec_time::numeric, 2) AS total_ms,
ROUND(mean_exec_time::numeric, 2) AS avg_ms,
LEFT(query, 200) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;SELECT
calls,
ROUND(total_exec_time::numeric, 2) AS total_ms,
ROUND(mean_exec_time::numeric, 2) AS avg_ms,
LEFT(query, 200) AS query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;This helps identify queries responsible for substantial cumulative database execution time.
Add Appropriate Indexes
Consider:
SELECT *
FROM rawaana_details
WHERE vehicle_no = 'HR01AB1234'
AND status = 'I';SELECT *
FROM rawaana_details
WHERE vehicle_no = 'HR01AB1234'
AND status = 'I';A potentially useful index:
CREATE INDEX CONCURRENTLY idx_rawaana_vehicle_status
ON rawaana_details (vehicle_no, status);CREATE INDEX CONCURRENTLY idx_rawaana_vehicle_status
ON rawaana_details (vehicle_no, status);Before adding indexes, examine actual execution plans and workload patterns.
Indexes can improve read performance but increase storage usage and write overhead.
CREATE INDEX CONCURRENTLY cannot execute inside an explicit transaction block.
Consider Connection Pooling
PgBouncer can help manage PostgreSQL connections in high-concurrency environments.
Connection pooling reduces some connection-management overhead, but does not fix inefficient SQL queries.
14. Use CDN and Edge-Level DDoS Protection
A CDN or managed DDoS protection provider can filter suspicious traffic before it reaches the origin server.
This is particularly important for volumetric attacks.
If an attacker saturates the network connection upstream, Apache configuration changes cannot recover the lost bandwidth.
Useful CDN and WAF Capabilities
- Network-layer DDoS protection
- HTTP request filtering
- Bot detection
- Rate limiting
- Geographic restrictions
- Managed challenges
- Static content caching
- Origin IP protection
- Traffic analytics
- Automated alerts
Example Endpoint Protection Policy
These are illustrative thresholds.
Real production limits should be based on measured request rates and application requirements.
Prevent Origin Server Bypass
A common mistake is placing a CDN in front of a website while leaving the origin publicly accessible.
An attacker may bypass the CDN and send traffic directly to the origin server.
Where supported, configure the origin firewall to accept application traffic only from approved CDN or reverse-proxy networks.
Ensure the application trusts only authorized forwarding proxies.
15. Configure Linux Firewall Protection
RHEL-based systems commonly use Firewalld.
Check Firewall Status
sudo firewall-cmd --statesudo firewall-cmd --stateList Firewall Rules
sudo firewall-cmd --list-allsudo firewall-cmd --list-allCheck Allowed Services
sudo firewall-cmd --list-servicessudo firewall-cmd --list-servicesAllow HTTP and HTTPS
Where required:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reloadsudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reloadThese commands allow HTTP and HTTPS traffic; they do not independently prevent DDoS attacks.
Block a Confirmed Malicious IP
sudo firewall-cmd --permanent \
--add-rich-rule='rule family="ipv4" source address="192.0.2.10" drop'sudo firewall-cmd --permanent \
--add-rich-rule='rule family="ipv4" source address="192.0.2.10" drop'Reload:
sudo firewall-cmd --reloadsudo firewall-cmd --reloadThe address shown is a documentation-only example.
Before modifying production firewall rules, verify that SSH management access will remain available.
Individual IP blocking is usually insufficient against large distributed attacks.
16. Use Fail2ban for Repeated Abuse
Fail2ban monitors logs and can temporarily ban IP addresses matching configured failure patterns.
It can help mitigate repeated authentication failures and certain automated scanning activities.
Install Fail2ban
Where available:
sudo dnf install fail2bansudo dnf install fail2banEnable it:
sudo systemctl enable --now fail2bansudo systemctl enable --now fail2banExample Jail Configuration
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/httpd/error_log
maxretry = 5
findtime = 600
bantime = 3600[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/httpd/error_log
maxretry = 5
findtime = 600
bantime = 3600Verify that the filter matches the actual Apache log format before enabling automatic bans.
Fail2ban is a complementary defense and is not designed to absorb large volumetric DDoS attacks.
When Apache is behind a proxy, ensure bans are not accidentally applied to the proxy's shared IP address.
17. Protect Expensive Laravel Endpoints
Not all HTTP requests consume the same resources.
A simple page may execute quickly, while a report-generation endpoint may perform several SQL joins, aggregation queries, file operations, and PDF generation.
An attacker can exploit this difference by repeatedly requesting expensive endpoints.
Example Report Endpoint
GET /reports/monthly-productionGET /reports/monthly-productionSuppose each request:
- Reads a large PostgreSQL table.
- Joins multiple related tables.
- Calculates summary totals.
- Generates an Excel file.
- Sends the file to the user.
Repeated requests may exhaust application and database resources.
Apply Authentication and Throttling
Route::middleware([
'auth',
'throttle:reports'
])->post('/reports/generate', [
ReportController::class,
'generate'
]);Route::middleware([
'auth',
'throttle:reports'
])->post('/reports/generate', [
ReportController::class,
'generate'
]);Register the reports limiter before using it.
Move Large Reports to Queues
Instead of generating reports during an HTTP request, dispatch a background job.
public function generate(Request $request)
{
$filters = $request->validate([
'from_date' => ['required', 'date'],
'to_date' => [
'required',
'date',
'after_or_equal:from_date'
],
]);
GenerateReportJob::dispatch(
auth()->id(),
$filters
);
return response()->json([
'message' => 'Report generation queued successfully.'
], 202);
}public function generate(Request $request)
{
$filters = $request->validate([
'from_date' => ['required', 'date'],
'to_date' => [
'required',
'date',
'after_or_equal:from_date'
],
]);
GenerateReportJob::dispatch(
auth()->id(),
$filters
);
return response()->json([
'message' => 'Report generation queued successfully.'
], 202);
}Background processing can reduce HTTP request duration.
However, queue workers also need concurrency limits, job timeouts, resource monitoring, and per-user quotas.
Otherwise, abusive traffic can overload the queue system instead of PHP-FPM.
18. Optimize Laravel Production Performance
Laravel production optimization reduces the amount of work required for each request.
Cache Configuration
php artisan config:cachephp artisan config:cacheCache Routes
php artisan route:cachephp artisan route:cacheCache Views
php artisan view:cachephp artisan view:cacheOptimize Composer Dependencies
composer install --no-dev --optimize-autoloadercomposer install --no-dev --optimize-autoloaderUse the application's existing lockfile and approved deployment process.
Disable Debug Mode
APP_ENV=production
APP_DEBUG=falseAPP_ENV=production
APP_DEBUG=falseDebug mode should never be publicly enabled on a production application.
Enable PHP OPcache
Example:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0When timestamp validation is disabled, the deployment process must reset OPcache or reload the relevant PHP processes after code changes.
These optimizations improve application efficiency but are not substitutes for DDoS mitigation.
19. Configure Trusted Proxies Correctly
Applications behind a CDN or load balancer need accurate client IP identification.
Without correct proxy configuration, Laravel may identify every request as coming from the same proxy address.
This can cause rate limiting to block legitimate users together.
Conversely, trusting arbitrary forwarding headers can allow attackers to spoof client IP addresses.
Check Apache RemoteIP Module
httpd -M | grep remoteiphttpd -M | grep remoteipExample Configuration
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 192.0.2.20RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 192.0.2.20Replace the example address with the actual trusted proxy address.
Configure Laravel's trusted-proxy handling consistently with the infrastructure.
The exact Laravel configuration differs by framework version.
Never trust arbitrary client-provided X-Forwarded-For headers.
20. Enable Apache Server Status Monitoring
Apache mod_status provides useful runtime metrics.
Check whether the module is enabled:
httpd -M | grep statushttpd -M | grep statusExample:
ExtendedStatus On
<Location "/server-status">
SetHandler server-status
Require local
</Location>ExtendedStatus On
<Location "/server-status">
SetHandler server-status
Require local
</Location>This restricts access to the local server.
Never expose detailed server status publicly.
Important Metrics
Monitor:
- Busy workers
- Idle workers
- Requests per second
- Bytes served
- Worker scoreboard states
- Request processing times
- Worker saturation
Check Apache Errors
sudo tail -f /var/log/httpd/error_logsudo tail -f /var/log/httpd/error_logSearch for important warnings:
sudo grep -Ei \
"MaxRequestWorkers|scoreboard|timeout|proxy" \
/var/log/httpd/error_logsudo grep -Ei \
"MaxRequestWorkers|scoreboard|timeout|proxy" \
/var/log/httpd/error_logA scoreboard-full message may indicate process-slot exhaustion or lingering connections.
Do not assume increasing MaxRequestWorkers is always the correct solution.
21. Understand HTTP 503 and 504 Errors
HTTP 503: Service Unavailable
HTTP 503 indicates that a service cannot currently handle the request.
Possible causes include:
- Apache worker exhaustion
- PHP-FPM saturation
- Application maintenance
- Backend connection failures
- Upstream service overload
HTTP 504: Gateway Timeout
HTTP 504 indicates that a gateway or proxy did not receive a timely response from an upstream service.
Possible causes include:
- Slow PHP execution
- Slow database queries
- External API delays
- Backend overload
- Proxy timeout settings
Recommended Troubleshooting Flow
HTTP 503 / 504 Error
|
v
Check Apache Access and Error Logs
|
v
Check Apache Worker Utilization
|
v
Check PHP-FPM Processes and Queues
|
v
Check Laravel Application Logs
|
v
Check PostgreSQL Query Performance
|
v
Check Network and Upstream Services
|
v
Apply Targeted Mitigation
|
v
Verify Application RecoveryHTTP 503 / 504 Error
|
v
Check Apache Access and Error Logs
|
v
Check Apache Worker Utilization
|
v
Check PHP-FPM Processes and Queues
|
v
Check Laravel Application Logs
|
v
Check PostgreSQL Query Performance
|
v
Check Network and Upstream Services
|
v
Apply Targeted Mitigation
|
v
Verify Application RecoveryAvoid restarting every service immediately.
Restarting may temporarily clear queues but can destroy useful diagnostic information and leave the underlying problem unresolved.
22. Monitor Incoming and Outgoing Bandwidth
Bandwidth monitoring is essential for distinguishing network saturation from application-layer overload.
Check Network Interfaces
ip -s linkip -s linkView Interface Statistics
cat /proc/net/devcat /proc/net/devMonitor Network Usage
Where installed:
sar -n DEV 1 5sar -n DEV 1 5Or:
iftopiftopImportant Bandwidth Metrics
Suppose a hosting provider permits 1 Gbps of inbound bandwidth.
If attack traffic exceeds the upstream capacity, Apache-side rules cannot prevent the connection from becoming saturated.
Upstream mitigation is required.
Maintain Historical Reports
Collect:
- Hourly incoming bandwidth
- Hourly outgoing bandwidth
- Maximum permitted bandwidth
- Peak request rates
- Connection counts
- Packet drops
- Firewall blocks
- WAF mitigation events
Historical data makes it easier to distinguish unusual traffic from normal daily patterns.
23. Implement Real-Time Monitoring and Alerts
Production infrastructure should not depend entirely on users reporting website slowness.
Continuous monitoring helps teams detect abnormal conditions earlier.
Useful tools include:
- Prometheus
- Grafana
- Zabbix
- Netdata
- Apache exporters
- PHP-FPM exporters
- PostgreSQL exporters
- Centralized log management platforms
Example Alert Thresholds
These thresholds are examples, not universal recommendations.
Example Alert Logic
IF HTTP 5xx error rate > 2%
AND PHP-FPM utilization > 85%
FOR 5 minutes
THEN send critical alertIF HTTP 5xx error rate > 2%
AND PHP-FPM utilization > 85%
FOR 5 minutes
THEN send critical alertAnother example:
IF incoming request rate > 3x normal baseline
AND WAF blocked requests increase sharply
THEN trigger traffic anomaly alertIF incoming request rate > 3x normal baseline
AND WAF blocked requests increase sharply
THEN trigger traffic anomaly alertThe actual implementation depends on the monitoring platform.
24. Emergency DDoS Incident Response Plan
When a production application experiences severe degradation, the first priority is maintaining availability while preserving evidence.
Phase 1: Initial Investigation (0–5 Minutes)
Check:
uptime
free -h
top -b -n1 | head -30
ss -s
sudo systemctl status httpd
sudo systemctl status php-fpmuptime
free -h
top -b -n1 | head -30
ss -s
sudo systemctl status httpd
sudo systemctl status php-fpmRecord current server utilization and application symptoms.
Phase 2: Identify the Bottleneck (5–15 Minutes)
Investigate:
- Apache request rates
- HTTP error rates
- PHP-FPM worker utilization
- PHP-FPM slow logs
- PostgreSQL query performance
- Network bandwidth
- WAF events
Determine whether the primary issue is network saturation, HTTP flooding, slow application processing, or database contention.
Phase 3: Apply Mitigation (15–30 Minutes)
Depending on the evidence:
- Activate or tighten upstream DDoS protection.
- Apply endpoint-specific rate limits.
- Block clearly abusive traffic.
- Reduce nonessential background workloads.
- Temporarily limit expensive application features.
- Coordinate with the hosting or network provider.
Avoid broad geographic restrictions unless their effect on legitimate users has been evaluated and the change is approved.
Phase 4: Verify Recovery
Confirm:
- Normal application response times
- Reduced HTTP 5xx error rates
- Healthy PHP-FPM queues
- Acceptable Apache worker utilization
- Stable database performance
- Successful critical transactions
A homepage returning HTTP 200 does not prove the entire application is healthy.
Phase 5: Post-Incident Review
Document:
- Incident timeline
- Observed traffic patterns
- Affected services
- Root cause or supported hypothesis
- Actions taken
- Recovery time
- Permanent corrective measures
25. Example Production Incident Scenario
Consider a hypothetical government-style Laravel portal used for online permits, payments, transport documentation, and administrative reports.
The infrastructure consists of:
During a traffic incident, the website begins responding slowly.
Apache logs show a significant increase in requests to several endpoints.
PHP-FPM logs show long-running requests, while active workers approach the configured maximum.
The server's CPU remains relatively idle.
Investigation
The team discovers that some requests execute expensive database queries and generate documents.
Under high concurrency, these requests keep PHP-FPM workers occupied.
Apache begins accumulating requests waiting for backend processing capacity.
The traffic may include malicious requests, legitimate demand, or both.
Corrective Actions
The team implements:
- Upstream request filtering
- Endpoint-specific rate limits
- PHP-FPM monitoring
- Database query optimization
- Apache configuration adjustments
- Centralized traffic monitoring
- Incident response procedures
Instead of relying only on hardware upgrades, the team measures the throughput and latency of each layer.
Expected Benefits
With properly tested controls, the application becomes better positioned to reject abusive requests early, preserve resources for legitimate users, reduce unnecessary database load, and recover from sudden traffic spikes.
Actual performance improvements must be validated through authorized load testing and production monitoring.
26. Common DDoS Protection Mistakes
Mistake 1: Increasing Server Resources Without Identifying the Bottleneck
Additional CPU and RAM can help certain workloads, but they do not solve every application-layer overload.
Mistake 2: Setting Apache Workers Too High
Increasing MaxRequestWorkers without measuring downstream capacity may overwhelm PHP-FPM or PostgreSQL.
Mistake 3: Increasing PHP-FPM Workers Without Database Planning
More PHP workers can generate more simultaneous database queries, increasing contention.
Mistake 4: Blocking Entire Countries Without Evaluating Impact
Geographic restrictions may block legitimate users and should be based on application requirements and approved policies.
Mistake 5: Exposing the Origin Behind a CDN
Attackers may bypass edge protection if the origin remains directly accessible.
Mistake 6: Trusting Arbitrary Forwarding Headers
Incorrect proxy configuration can permit IP spoofing and rate-limit bypasses.
Mistake 7: Depending Only on CAPTCHA
CAPTCHA can reduce certain automated submissions, but it does not stop network saturation or every HTTP flood.
Mistake 8: Ignoring Database Performance
A relatively small number of expensive SQL queries can significantly degrade an application.
Mistake 9: Restarting Services Without Investigation
Restarts may temporarily restore availability but can destroy evidence and leave the underlying issue unresolved.
Mistake 10: Assuming HTTP 200 Means Complete Recovery
Verify authentication, APIs, payments, reports, database transactions, and critical user journeys.
27. Production Security Checklist for 2026
Before declaring an Apache and Laravel application production-ready, verify the following:
- Upstream CDN/WAF and DDoS protection are configured.
- Direct origin access is restricted where possible.
- Apache Event MPM capacity has been measured.
- KeepAlive and request timeouts are appropriately configured.
- ModSecurity rules have been tested.
- Laravel rate limiting protects expensive endpoints.
- Redis is used for shared counters where appropriate.
- Trusted proxy configuration is correct.
- PHP-FPM worker limits are based on measured capacity.
- PHP-FPM slow logging is enabled.
- PostgreSQL slow queries are monitored.
- Database connections are monitored.
- Administrative and monitoring endpoints are restricted.
- Centralized logging is enabled.
- Real-time alerts are configured.
- Backups and rollback procedures are tested.
- Authorized load testing has been performed.
- An incident response plan is documented.
28. The Future of DDoS Protection
DDoS defense is increasingly focused on layered traffic analysis, automated response, and application-aware protection.
Modern security systems can combine network telemetry, request patterns, bot signals, and application metrics to identify suspicious behavior.
Potential improvements include:
- Adaptive rate limiting
- Managed bot protection
- Automated traffic anomaly detection
- Application-aware security policies
- Real-time mitigation alerts
- Improved observability
- Resilient load balancing
- Continuous capacity testing
However, automated security controls must be carefully tuned.
False positives can prevent legitimate users from accessing essential services.
The objective is not simply to block as many requests as possible.
The objective is to distinguish harmful traffic from legitimate demand while maintaining service availability.
Conclusion
Protecting Apache and Laravel applications from DDoS attacks requires more than installing a firewall or upgrading server hardware.
Even powerful infrastructure with dozens of CPU cores and large amounts of RAM can experience severe performance degradation when Apache workers, PHP-FPM processes, database connections, or network bandwidth become exhausted.
A reliable defense requires multiple layers.
Network-level protection should filter large floods before they reach the origin server.
Apache should be configured to handle connections efficiently.
PHP-FPM should have realistic worker limits based on measured capacity.
Laravel should enforce appropriate rate limits and protect expensive operations.
PostgreSQL queries should be continuously monitored and optimized.
Real-time monitoring should provide visibility into request rates, server utilization, network bandwidth, database performance, and HTTP errors.
Most importantly, organizations should maintain tested incident response procedures so that technical teams can investigate and mitigate traffic incidents quickly.
There is no single configuration that guarantees protection against every DDoS attack. But a well-designed, monitored, and regularly tested infrastructure can significantly improve resilience and preserve availability for legitimate users.
The ultimate goal is not just to stop malicious traffic.
It is to keep critical applications secure, responsive, and available when users need them most.
References
- Apache HTTP Server Documentation — https://httpd.apache.org/docs/2.4/
- Laravel Rate Limiting — https://laravel.com/docs/12.x/rate-limiting
- PHP-FPM Configuration — https://www.php.net/manual/en/install.fpm.configuration.php
- PostgreSQL Monitoring Statistics — https://www.postgresql.org/docs/current/monitoring-stats.html
- OWASP Denial of Service Cheat Sheet — https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html
- Cloudflare DDoS Protection — https://developers.cloudflare.com/ddos-protection/
Disclaimer: The configurations, IP addresses, thresholds, and infrastructure examples in this article are illustrative. Always test changes in staging and adapt them to the production workload, operating system, software versions, and security requirements. Perform load testing only on systems you own or are explicitly authorized to test.