Email WhatsApp
WeChat
WeChat QR

Table of Contents

KiwiPi 5 as a Single-Board Server

We ran a Python web application on an 8GB KiwiPi 5 and tested it over Gigabit Ethernet. We built the application, KiwiPi Server Lab, specifically for this experiment; it’s a test program, not a released monitoring product.

At 32 concurrent connections, this single-board server returned a median 5,063 HTML responses per second. Reading 120 history records from SQLite brought that down to 1,481. The board and server configuration stayed the same; the requests did different work and returned different amounts of data.

Single-Board Server

The KiwiPi 5 test system

The board ran Ubuntu 24.04.3 LTS, kernel 6.1.141, and Python 3.12.3. Its RK3588S has four Cortex-A55 and four Cortex-A76 cores, with 8GB of installed RAM. The app and database lived on eMMC, and both the board and the separate Windows load-generator PC used wired Gigabit Ethernet.

The installed image exposed CPU frequency limits of 1.8GHz and 2.352GHz, with the schedutil governor changing clocks automatically. That’s the configuration behind these results, even though the product page lists a different maximum A76 frequency. Swap was off.

We left GNOME and the KiwiDrop local file sharing app running. During the 30-second baseline, total CPU usage already averaged 37.3%, with the SoC at 41.3°C. We used a heatsink and fan with no enclosure; room temperature was approximately 26°C. Power came through USB-C; adapter ratings and actual consumption weren’t measured.

Component Tested configuration
Board and SoC KiwiPi 5, RK3588S, V20 device-tree identification
CPU 4 × Cortex-A76 and 4 × Cortex-A55
CPU limits exposed by this image A76 up to 2.352GHz; A55 up to 1.8GHz; automatic schedutil governor
Memory 8GB installed; about 7.73GiB visible to Linux; no swap
Application storage Onboard eMMC; ext4 root filesystem
Network Ethernet at 1,000Mbit/s, full duplex
Operating system Ubuntu 24.04.3 LTS; Linux 6.1.141
Web stack Python 3.12.3; Gunicorn 23.0.0; four workers with two threads each
Cooling and power Heatsink and fan, no enclosure; USB-C power
Recorded SSH output identifying the test board, Linux kernel, Python version, memory, storage, and Ethernet connection.
Recorded SSH output identifying the test board, Linux kernel, Python version, memory, storage, and Ethernet connection.


Other boards in the KiwiPi series

The series has higher-spec options when a server needs more storage or network bandwidth. The KiwiPi 5 Pro board uses RK3588, with up to 32GB RAM, two 2.5GbE ports, and an M.2 2280 slot connected through PCIe 3.0 x4. KiwiPi 5B development hardware also uses RK3588 and provides an M.2 2280 PCIe 3.0 slot for an NVMe SSD.

Those are useful expansion options for a database or networked-storage project. Both models retain the four-A76, four-A55 CPU arrangement, so the specifications alone don’t establish a CPU-performance advantage over this KiwiPi 5. Neither was included in our test, and the throughput results below apply only to the tested board.

A web app built for this test

A separate collector reads Linux telemetry once a second, writes a record to SQLite, and atomically replaces a JSON snapshot. The dashboard polls every five seconds and shows CPU, temperature, memory, and storage use. It runs on the board, with no CDN assets or cloud backend.

The three tested routes have deliberately different jobs. / returns the dashboard’s HTML, /api/current reads the existing snapshot, and /api/history?limit=120 opens a read-only SQLite connection and returns 120 records as JSON. The HTML is loaded into each worker’s memory at startup. Requesting the current snapshot doesn’t resample all the sensors. Fetching the HTML doesn’t reproduce a browser session with its subsequent API and logo requests.

The collector keeps up to 24 hours of history in SQLite WAL mode. SQLite’s write-ahead logging documentation explains how readers and a writer can run concurrently; here, one collector writes while the web workers read. Those small, frequently accessed queries aren’t a benchmark of raw eMMC speed or a large database.

Gunicorn 23.0.0 served the WSGI app through four gthread workers, with two threads per worker and a five-second HTTP/1.1 keep-alive. We didn’t put Nginx, TLS, or HTTP/2 in front of it.

KiwiPi Server Lab dashboard running on KiwiPi 5 before the load test
KiwiPi Server Lab before the measured runs. Other desktop applications were already running.

Starting the lab application

With the lab files in ~/kiwipi-server-lab, the tested installation and start commands were:

Bash

cd ~/kiwipi-server-lab
python3 -m pip install --target vendor -r requirements.txt
sh start.sh

Dependencies stayed in the application’s vendor directory. The script started separate transient systemd user services for the collector and web app, without replacing existing services. If you’re administering from a Mac, connecting to the board over SSH gives you a terminal for these commands.

Recorded SSH output checking Gunicorn, the lab services, and the health endpoint.
Recorded SSH output checking Gunicorn, the lab services, and the health endpoint.

The test app listened on 192.168.3.99:8095; another board needs its own address through LAB_BIND. It has no authentication and was used on the local test network. The services weren’t enabled at boot. To stop both:

Bash

systemctl --user stop kiwipi-server-lab-web kiwipi-server-lab-collector

HTTP throughput and latency

What the generator measured

A separate Core i7-12700KF PC running Node.js 24.19.0 sent requests through 1, 8, or 32 persistent connections. Each connection waited for its response and immediately requested another, without user think time. After baseline collection and warmups, we ran each route at each connection count three times for 20 seconds: 27 measured runs, with the route order rotated between repetitions.

Latency covered the time from request creation to receipt of the complete response at the client. All HTTP statuses were checked, while response bodies were checked on a sample. The final short runs and five-minute run completed 1,470,216 responses, with zero recorded HTTP/transport errors and zero failures among 1,906 sampled body checks. Warmups and an interrupted pilot are excluded; the pilot exposed a client-side body-validation bug fixed before the final series.

HTML and JSON results

These are medians of three runs. The RPS range shows the lowest and highest run; p95 is the median of the three runs’ individual p95 values, not a pooled percentile across all requests.

Request Connections Responses/s Run range p95 ms
HTML page 1 454 452–471 5.4
HTML page 8 2,472 2,424–2,528 10.6
HTML page 32 5,063 4,967–6,383 18.0
Current snapshot 1 377 377–388 6.7
Current snapshot 8 1,707 1,191–1,780 14.4
Current snapshot 32 3,116 2,260–6,180 30.9
SQLite history 1 156 148–157 12.4
SQLite history 8 991 975–1,060 17.5
SQLite history 32 1,481 1,437–1,539 36.1
KiwiPi 5 HTTP throughput and p95 latency at 1, 8 and 32 connections
Medians of three 20-second runs. Throughput whiskers show the minimum and maximum across repetitions.

More connections raised total throughput, but also raised latency. For history, p95 went from 12.4ms at one connection to 36.1ms at 32. The board was answering more requests overall, while an individual request generally waited longer.

The snapshot endpoint also varied a lot: 2,260–6,180 responses/s at 32 connections. We didn’t isolate the reason. Background work, scheduling, automatic clocks, and caches remained variables, so 6,180 isn’t a sensible figure to present as its typical speed.

KiwiPi 5 dashboard showing CPU use and SoC temperature during HTTP load
The dashboard during the first HTML run at 32 connections. These are instantaneous readings, not run averages.

The history response also fills the network

The five-minute history run returned about 74.3kB per response on average. Dividing its recorded response-body bytes by elapsed time gives roughly 910Mbit/s of payload, before HTTP and network overhead, on a 1Gbit/s link.

That makes network capacity a plausible constraint, rather than proof that SQLite or the CPU had reached its limit. We didn’t record NIC-level utilisation or repeat the test with a faster link. Reducing the response size would be a useful next experiment.

Five minutes of continuous requests

The history endpoint then ran for 300 seconds at 32 connections. It completed 459,019 responses at 1,530 responses/s, with p95 at 33.5ms and p99 at 43.5ms. There were no recorded HTTP/transport errors or failed sampled body checks during that run.

The highest sampled SoC temperature across the measured runs and continuous test was 57.3°C. The hottest reading from any thermal zone was 60.1°C; those are different measurements. Our guide to reading Linux CPU temperatures covers identifying the sensors. The cooling here included a fan, and these readings don’t prove the absence of every kind of throttling.

For the 32-connection history runs, median average total CPU usage was 67.7%, with the web service at 40.6% of the board’s eight-core capacity. That web-service figure excludes the collector. Other applications were still contributing to the whole-system total.

Web-service memory, measured as summed proportional set size (PSS), ranged from 32.5 to 39.8MiB during the five-minute run. It started at 39.6MiB and ended at 38.3MiB. That’s a short observation with no sustained increase, not a long-term leak test or the memory cost of the whole system.

Afterward, SQLite quick_check returned ok, and both lab services were active with zero recorded restarts. Functional checks also covered stale telemetry, invalid history parameters, and rejected requests. The screenshots show individual moments; the table reports aggregated runs.

KiwiPi 5 Five-Minute Server Test
KiwiPi 5 SoC temperature and web-service PSS during five minutes of history requests

FAQ

What can a single-board computer server run

This experiment supports using KiwiPi 5 for a small internal dashboard or local telemetry API with similar requests. A different application needs its own measurements. We didn’t test WordPress, large database writes, file uploads, TLS, or another board for comparison.

Do 32 connections mean 32 users

No. The generator sent another request immediately after each response. Browser users pause, fetch several resources, and may trigger different queries. These connection counts don’t establish a supported user count.

Is this enough evidence for an always-on server

It’s enough to describe this short LAN experiment. Before relying on a single-board server around the clock, extend the run, test your actual workload, and check recovery after restarting the services or board. The next useful result would come from those tests, rather than another peak RPS figure.

Related Products

Kiwipi-5

KiwiPi 5

The alternative to Raspberry Pi features an RK3588S octa-core 64-bit flagship processor. Built with 8nm technology, it incorporates an ARM Mali-G610 MP4 quad-core GPU and a 6TOPs AI NPU. Its architecture provides high performance and energy efficiency, making it suitable for intensive applications.

Kiwipi-5Pro

KiwiPi 5 Pro

KiwiPi 5 Pro is powered by Rockchip RK3588 8-core 64-bit processor with 4 Cortex-A76 (2.2GHz), 4 Cortex-A55(1.8GHz), and an independent NEON coprocessor.

Kiwipi-5B

KiwiPi 5B

The Kiwi Pi 5B RK3588 single-board computer (SBC), an alternative to the Raspberry Pi 5, features an 8-core CPU, Mali-G610 GPU, and 6 TOPS NPU.

Get in Touch about Your Needs

Contact Us