Conversation

Your input fuels progress! Share your tips or experiences on prioritizing mental wellness at work. Let's inspire change together!

Join the discussion and share your insights now!

Comments: 0

Sharpen your coding skills—try JavaScript challenges on TOOLX now!

advertisement

How to Limit and Rate-Limit Access to Your PHP API

How to Limit and Rate-Limit Access to Your PHP API

In the world of web development, ensuring that your APIs are secure and protected from abuse is critical. Whether you're offering a public-facing API or managing internal microservices, rate limiting helps prevent misuse, DDoS attacks, and system overload.

In this article, you'll learn how to implement rate limiting in a core PHP REST API, without using any external frameworks — complete with table creation, logic explanation, headers, and optional enhancements.


Why Rate Limiting is Important

  • Prevents abuse (bots or brute-force attacks)
  • Ensures fair usage for all users
  • Preserves server resources
  • Protects your database from being overloaded

What is Rate Limiting?

Rate limiting is the process of controlling the number of requests a user can make to an API within a specified time period.

For example:

Allow max 100 requests per IP address every 10 minutes.

If the client exceeds this limit, the API returns a 429 Too Many Requests response.


Rate Limiting in Core PHP


Step 1: Create the MySQL Table to Store IP Activity

CREATE TABLE api_limits (
    ip_address VARCHAR(45) NOT NULL,
    request_count INT DEFAULT 0,
    last_request_time DATETIME,
    PRIMARY KEY (ip_address)
);

This table keeps track of each IP address, how many requests it has made, and the last time it accessed your API.

Step 2: Create the PHP Logic to Enforce the Rate Limit

function limitRequestRate(PDO $db, $ip, $max_requests = 100, $interval_seconds = 600) {
    $stmt = $db->prepare("SELECT * FROM api_limits WHERE ip_address = ?");
    $stmt->execute([$ip]);
    $record = $stmt->fetch(PDO::FETCH_ASSOC);

    $now = new DateTime();

    if ($record) {
        $last_request_time = new DateTime($record['last_request_time']);
        $diff = $now->getTimestamp() - $last_request_time->getTimestamp();

        if ($diff <= $interval_seconds) {
            if ($record['request_count'] >= $max_requests) {
                http_response_code(429);
                echo json_encode(['error' => 'Rate limit exceeded. Try again later.']);
                exit;
            } else {
                $stmt = $db->prepare("UPDATE api_limits SET request_count = request_count + 1, last_request_time = NOW() WHERE ip_address = ?");
                $stmt->execute([$ip]);
            }
        } else {
            $stmt = $db->prepare("UPDATE api_limits SET request_count = 1, last_request_time = NOW() WHERE ip_address = ?");
            $stmt->execute([$ip]);
        }
    } else {
        $stmt = $db->prepare("INSERT INTO api_limits (ip_address, request_count, last_request_time) VALUES (?, 1, NOW())");
        $stmt->execute([$ip]);
    }
}

This function:

  • Checks if the IP exists in the database
  • If it does, and it's within the time window, it counts requests
  • If limit exceeded → blocks access
  • If time expired → resets the counter
  • If new IP → creates a new record

Step 3: Create the Database connection

<?php
function connectDB() {
    $host = 'localhost';
    $db = 'ratelimit';
    $user = 'root';
    $pass = '';
    $charset = 'utf8mb4';
    $dsn = "mysql:host=$host;dbname=$db;charset=$charset";
    try {
        return new PDO($dsn, $user, $pass, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
        ]);
    } catch (PDOException $e) {
        http_response_code(500);
        echo json_encode(['error' => 'Database connection failed']);
        exit;
    }
}
?>


Step 4: Use It in Your API Entry Point (index.php)

$ip = $_SERVER['REMOTE_ADDR'];
$db = connectDB();
limitRequestRate($db, $ip); // Call this before processing the API logic

This must be added before any sensitive logic in your REST API route.


Step 4: Add Optional Rate Limit Headers

These headers can help clients understand their limits:

header("X-RateLimit-Limit: 100");
header("X-RateLimit-Remaining: " . (100 - $record['request_count']));

You can also return:

header("Retry-After: 600"); // in seconds


Advanced Options

Once your basic rate limiter is running, consider improving it with:

  • Per-user limits: If users are authenticated (e.g. by token or API key), store usage by user_id instead of IP.
  • Redis/Memcached: For higher performance in high-traffic environments.
  • Auto-ban abusive IPs: If an IP constantly exceeds the limit, add it to a blacklist table.
  • Dynamic Limits: Adjust limit values per endpoint (e.g., login = 10, read = 1000).

Final Thoughts

Implementing rate limiting in core PHP is straightforward and highly effective. It’s one of the most essential safeguards you can add to any API-driven project.

  • Protects APIs from abuse
  • Keeps your database load stable
  • Improves app scalability


PHP APIs Rate limit api PHP rate limiting limit API requests in PHP API protection PHP PHP REST API security prevent abuse in PHP REST API

advertisement