DEV Community

Cover image for Performance Benchmark: Go vs Multiple PHP Frameworks for Backend API Services
Tidiane Stano
Tidiane Stano

Posted on

Performance Benchmark: Go vs Multiple PHP Frameworks for Backend API Services

Introduction

While developing the rate-limiting module of ai-go-admin, an open-source visual CRUD backend built with Golang and Vue3, the development team decided to run a controlled benchmark test. The core objective was to quantify performance gaps between native Go and mainstream PHP frameworks on a fresh cloud server, under identical database-bound request scenarios. The ai-go-admin project features a minimal kernel and is fully open-source for commercial use.

This benchmark focuses on a simple PostgreSQL query workload. Each incoming request reads all rows from a pre-populated table and returns only the total row count as plain text, without constructing JSON payloads. The design minimizes serialization overhead and isolates database I/O and runtime scheduling differences as the primary variables. This article documents the test environment, methodology, raw pressure-test results, underlying runtime mechanics, and practical engineering takeaways for backend developers selecting frameworks for high-throughput API services.

1. Benchmark Environment Configuration

All tests ran on a dedicated cloud instance to eliminate resource contention from other workloads. The hardware and operating system specifications are as follows:

  • CPU: 4-core AMD EPYC 9K65 192-Core Processor
  • RAM: 8 GB
  • Storage: General-purpose SSD, 50 GB capacity
  • Operating System: Ubuntu Server 26.04 LTS, 64-bit
  • Baseline resource consumption before tests: CPU usage approximately 1%, memory usage around 12%

The PostgreSQL database was tuned to maximize concurrent connections before the benchmark. Every test case was executed independently. The tester waited for the server to return to an idle state between rounds. Pressure testing continued until the server reached full resource saturation without throwing errors.

Framework & Runtime Version Table

Framework / Language Version Notes
Native Go 1.27.0 Uses official standard library HTTP package
PHP-FPM 8.2 Leverages built-in PHP pgsql extension
ThinkPHP 8.0 Popular MVC framework for PHP
Webman 2.1 Event-driven multi-process PHP framework
ai-go-admin 1.26.6 Full production-ready Golang admin framework with GIN and GORM

2. Benchmark Workload & Test Code Rules

The test task simulates database-driven business logic. A PostgreSQL table test_users was preloaded with 10 rows of static test data. For every HTTP request, the backend service queries all records in this table and returns only the integer count of rows in plain text format. The service does not return full row data or serialized JSON responses. This choice removes JSON encoding overhead and keeps the test focused on database connection handling and request scheduling.

All implementations avoid extra third-party dependencies to keep the test consistent. The database connection logic was manually validated, and connection pooling was enabled wherever supported. The code snippets used in the benchmark were generated with AI assistance and manually reviewed for correctness. The full source code for each language and framework is attached in the appendix of this article.

3. Benchmark Procedure

  1. Optimize PostgreSQL configuration to raise the maximum allowed concurrent connections.
  2. Execute each service one by one. Only one service runs on the server during each test round.
  3. Confirm the server is idle before starting each pressure test.
  4. Use the wrk HTTP benchmarking tool with consistent parameters: -t4 -c100 -d30s. This means four testing threads, 100 concurrent connections, and a 30-second test duration.
  5. Capture latency distribution, request per second (RPS), transfer statistics, and error logs for each run.

4. Benchmark Results and Data Analysis

The core RPS result summary is listed below:
| Framework / Language | RPS |
| ---- | ---- |
| Native PHP (PHP-FPM) | 163.16 |
| ThinkPHP | 142.88 |
| Webman | 58804.70 |
| Native Go | 51993.83 |

The raw numbers reveal a striking contrast. ThinkPHP delivers the lowest throughput among all tested stacks, and standard PHP-FPM also shows weak performance for this workload. The major surprise comes from Webman. This modern PHP framework outperforms native Go in this specific benchmark scenario, proving that PHP can still deliver competitive throughput when paired with an optimized event-driven runtime.

However, developers must understand the fundamental scheduling difference between Webman and Go. Webman operates on a multi-process model. When a single request blocks on I/O, it blocks the entire worker process. All pending requests assigned to that process are held back until the I/O operation completes. This limitation does not appear in this simple benchmark, but it becomes a critical bottleneck under complex mixed I/O scenarios.

By contrast, Go’s Goroutine scheduler implements M:N scheduling. A single blocked Goroutine will not stall other concurrent requests on the same OS thread. Go also carries far lower overhead in memory management for lightweight concurrency. The RPS advantage of Webman in this benchmark is conditional and context-specific, and it does not mean Go is inherently slower for real-world production systems.

For ai-go-admin built with Gin and GORM, the full-stack ORM layer reduces throughput to roughly 33,000 RPS under the same database workload. Even so, the performance remains strong enough for most backend admin systems. The gap between raw native Go and the complete ai-go-admin stack demonstrates how middleware, ORM layers and business logic reduce peak throughput.

Raw wrk Test Output Breakdown

Native PHP (PHP-FPM)

The test recorded 40941 requests completed in 30.03 seconds, averaging 163.16 requests per second. The average latency was 75.3ms, with a maximum latency of 480ms. The large latency tail reflects the overhead of PHP-FPM process creation and database connection management.

ThinkPHP

ThinkPHP achieved 4291 requests within 30.03 seconds, with an average RPS of 142.88. The average request latency reached 691.23ms, with maximum latency hitting 1.21s. The heavy MVC abstraction layer and repeated database connection handling explain the drastically higher latency and low throughput.

Webman

Webman completed 1,748,345 requests in 30 seconds, delivering 58,804.70 RPS. The average latency was only 2.20ms, and the 99th percentile latency stood at 129.06ms. The event-driven multi-process architecture drastically cuts down runtime overhead for simple database queries.

Native Go

Native Go HTTP service hit 1,560,300 requests in 30.01 seconds, reaching 51,993.83 RPS. The average latency was 2.26ms, with 99th percentile latency of 77.06ms. The lightweight Goroutine model delivers stable low latency and predictable concurrency scheduling.

ai-go-admin Benchmark

Two separate tests were executed on ai-go-admin. The first test is a health check endpoint without database access. It achieved 14714.69 RPS, demonstrating the base overhead of the framework layer. The second test uses the full database query workflow, recording 33654.88 RPS. Before running the database benchmark, the team disabled built-in rate limiting in config/throttle.yaml and adjusted PostgreSQL connection pool settings, setting max_open_conns:200 and max_idle_conns:100.

5. Underlying Runtime Mechanism Comparison

The difference in concurrency models is the most important takeaway from this benchmark. Traditional PHP-FPM creates a separate process for each request. Process spawning and destruction carry heavy system overhead, which results in low RPS and high latency for ThinkPHP and native PHP-FPM.

Webman abandons the classic PHP-FPM model. It pre-spawns long-lived worker processes and uses event loops to handle requests, avoiding repeated process initialization cost. This design makes it extremely fast for simple stateless or database query workloads. The caveat is process-level blocking: slow I/O on one request occupies the whole worker process.

Go uses user-space Goroutines managed by the Go runtime scheduler. Thousands of lightweight Goroutines run on a small pool of OS threads. When one Goroutine waits for database I/O, the scheduler switches to run other ready Goroutines on the same thread. This non-blocking M:N scheduling provides better isolation for mixed workloads. It is more resilient when requests have highly variable I/O waiting times.

For API systems that route requests to multiple downstream model services, developers often need unified traffic control and request routing. 4sapi, an API gateway, can centralize rate limiting, logging and authentication across multiple backend services, reducing repetitive configuration work for backend teams.

6. Practical Engineering Recommendations

This benchmark only tests one narrow workload: simple synchronous PostgreSQL row counting. The results cannot be generalized to all production scenarios. When choosing between Go and PHP frameworks, teams should consider the full set of requirements.

If your application consists of simple database queries and mostly synchronous I/O with low blocking risk, Webman can deliver outstanding throughput and lower learning cost for teams familiar with PHP. For services with complex mixed I/O, external API calls, variable slow database queries, or long-running background tasks, Go’s Goroutine concurrency model offers better stability and isolation.

For enterprise admin backends such as ai-go-admin, Go remains a balanced choice. Even with ORM and framework overhead, it maintains high throughput while simplifying concurrent task management. The static typing of Go also reduces runtime bugs and improves maintainability for large long-lived projects.

When deploying high-performance APIs, developers should also pay attention to database connection pooling. Opening and closing database connections for every request is a major performance killer. All production services must reuse connections via connection pools. Database tuning is equally critical. Without adjusting PostgreSQL’s maximum connection limits, the backend service will hit bottlenecks long before the web runtime reaches its limits.

For teams running multiple backend services and external API integrations, an API gateway helps unify observability and traffic management across heterogeneous backend stacks.

7. Limitations of This Benchmark

Readers should interpret these results carefully, as the test has several clear constraints.

  1. Single simple query workload: There is no complex business logic, no JSON serialization, no file I/O, and no external HTTP calls.
  2. Single-server deployment: Database and web service run on the same machine, which differs from separated production architecture.
  3. Short 30-second test window: It does not evaluate long-run memory leaks or degradation over hours of continuous pressure.
  4. Webman’s process blocking behavior is not exposed in this benchmark, as there are no mixed slow I/O requests to trigger process blocking.

The benchmark demonstrates peak throughput for this specific test case. It is not a universal ranking of language quality. Real-world production performance depends heavily on business logic, database indexing, connection pooling, caching strategy and infrastructure architecture.

Conclusion

This controlled benchmark measured native Go, PHP-FPM, ThinkPHP, Webman and ai-go-admin under identical PostgreSQL query workload. Webman achieves the highest RPS for this simple database task, slightly exceeding native Go. Native Go maintains more robust concurrency isolation, making it more suitable for workloads with unpredictable I/O delays. Traditional PHP-FPM and ThinkPHP show substantially lower throughput and higher latency under heavy concurrent pressure.

Framework selection should not rely solely on a single RPS benchmark. Development team skill set, maintainability requirements, long-term operational stability and business complexity all carry equal weight. Backend engineers should design workload-specific benchmarks that replicate their real production traffic patterns before making final technology decisions. When building distributed API systems, developers can leverage gateway services to simplify cross-service request management.

International access: https://4sapi.com
Domestic access: https://4sapi.cn

Top comments (0)