What a €40 server can do
Over 4 million companies and tens of millions of records. A single server. No microservices, no Kubernetes, no buzzwords.
Live test
100 real queries, 20 concurrent, against the production database
Press the button to run 100 real queries and measure server capacity.
Methodology
What we measure
The capacity test runs 100 real queries (company search, people search, CUI details, IBAN), 20 at a time, against the production database with over 4 million companies, representatives, and tens of millions of interconnected records. The concurrent user estimate assumes a real user makes on average 1 request every 3 seconds (page load + think time).
How we measure
Query functions are called directly on the server (no HTTP overhead), and time is measured with performance.now() — sub-millisecond resolution. Results include only server processing time, not network latency.
Formula
concurrent users = requests/second × 3s (avg time between actions)
Why it matters
A €40/month server with a well-indexed database and Bun as the runtime can serve thousands of concurrent users. No microservices, no Kubernetes, no million-dollar infrastructure needed.
What it costs elsewhere
The same server (8 vCPU, 16 GB RAM) at different providers — monthly prices, no discounts
Hyperscalers (AWS, Google, Azure) offer managed services, but for a portal with a well-indexed database, a simple VPS delivers the same performance at a fraction of the cost.
Test it yourself
Install k6 (open source, single binary) and run the script below.
import http from 'k6/http';
import { check, sleep } from 'k6';
// 50 utilizatori virtuali, 30 secunde
export const options = {
stages: [
{ duration: '10s', target: 50 },
{ duration: '15s', target: 50 },
{ duration: '5s', target: 0 },
],
};
const BASE = 'https://demoanaf.ro';
const SEARCHES = ['construct', 'transport', 'consult', 'auto', 'euro'];
const PEOPLE = ['pop', 'ion', 'maria', 'gheorghe'];
const CUIS = [33503335, 4221306, 14399840, 18189442];
function pick(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
export default function () {
const roll = Math.random();
let res;
if (roll < 0.4)
res = http.get(BASE + '/api/search?q=' + pick(SEARCHES) + '&limit=10');
else if (roll < 0.65)
res = http.get(BASE + '/api/company/' + pick(CUIS));
else if (roll < 0.85)
res = http.get(BASE + '/api/search/people?q=' + pick(PEOPLE) + '&limit=10');
else
res = http.get(BASE + '/api/iban?q=timis');
check(res, {
'status 200': (r) => r.status === 200,
'response < 500ms': (r) => r.timings.duration < 500,
});
sleep(0.5);
}Your results will include network latency — ours are measured directly on the server. The script uses 50 virtual users for 30 seconds, with a 0.5s pause between requests.