Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Velocity web server

This page is for administrators who want to serve Exponential faster with fewer moving parts, and for anyone deciding whether to use Velocity. Velocity is a web server written in PHP that runs your Exponential…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/features/6.0/velocity-web-server.md

On this page

Velocity web server

This page is for administrators who want to serve Exponential faster with fewer moving parts, and for anyone deciding whether to use Velocity. Velocity is a web server written in PHP that runs your Exponential installation (or any PHP application) from a pool of long-lived PHP processes. It answers HTTP/1.1, HTTP/2 over TLS and WebSockets itself, serves static files, caches pages in its own process, and keeps the application loaded between requests. You do not need Apache, nginx or PHP-FPM in front of it, though it works behind them. Applies to Exponential 6.0.x with Exponential Velocity 0.0.4.x.

Warning

.htaccess slows down every request. When .htaccess files are enabled (AllowOverride anything but None), let alone used, Apache looks for them and reads and evaluates them on every request, in every directory of the path, and page loading times go up drastically (measured). The only real fix is to switch the feature off for the virtual host: AllowOverride None in the HTTPS virtual host, and the rules in the virtual host's own configuration as mod_rewrite rules. That is far faster in production speed tests and well worth the time it takes to optimize a production configuration. Switch over right away: copy the rules of the example HTTPS virtual host into your virtual host (with the static cache, also staticcache_offload.conf), set AllowOverride None, run apachectl configtest, reload Apache and test the site. The same rules for other servers: nginx, LiteSpeed, Caddy, IIS, Velocity (built in); where virtual host rules go in a control panel: Plesk, cPanel, DirectAdmin, ISPConfig. On LiteSpeed or OpenLiteSpeed, the server's own page cache can also answer anonymous visitors and crawlers without PHP: Page caching with LiteSpeed and OpenLiteSpeed.

The engine comes from the Qbix web server and ships as the Composer package se7enxweb/exponential-velocity (earlier se7enxweb/qbix-webserver). Exponential drives it with exp:velocity; the engine's own programs are qbixserver, qbixctl and qbixconsole.

Part of Exponential as of 6.0.15

As of Exponential 6.0.15 the Velocity Internet / Web Application Server is part of Exponential. The root composer.json requires se7enxweb/exponential-velocity ~0.0.4.57 (through se7enxweb/exponential-php-floor, on PHP 8.0 and later) (it was a suggestion before), so every installation made with composer install has the server, on PHP 8.0 and later, the stock PHP 8.0 of Red Hat Enterprise Linux 9 included. It runs next to Apache with PHP-FPM, nginx and FrankenPHP: its own server is the recommended engine for every stage, FrankenPHP is the production-ready alternative, and the traditional servers keep working as before.

That marks a turning point for the project, a cornerstone and a capstone: a new level of application system integration in which the core product provides even greater features out of the box, by default. With the server in the box, Exponential is one working stack (server, rapid application development platform, CMS, digital experience and e-commerce) rather than a framework to complete. The whole story, for every reader: Velocity is part of Exponential 6.0.15. Every other feature page: Exponential 6.0 features.

The commands of daily work are ./console exp:velocity deploy, start, restart and cache clear.

Start it in two minutes

From an Exponential installation, use the console command (see Velocity engines for all verbs and velocity.ini):

./bin/php/console exp:velocity status --allow-root-user
./bin/php/console exp:velocity start --engine=qbix --allow-root-user

Without Exponential, from the engine's own tree:

mkdir -p web && echo '<?php echo "Hello!";' > web/index.php
php sbin/qbixserver.php --root=web --port=8080

Open http://localhost:8080/ (it prints Hello!) and http://localhost:8080/Q/dashboard. Stop it with php sbin/qbixserver.php --stop (uses the pid file) or qbixctl stop.

Why use it

  • Speed without a stack. One PHP process tree answers everything. Cached public pages are answered in the server process before any worker is chosen, so a hit costs about 0.2 to 0.4 ms of CPU. Measured on one 12-core host with an Exponential front page over TLS and gzip: about 2,950 cached pages a second from one server, about 12,000 from four servers on one port (Velocity engines).
  • Persistent workers. The application is loaded once in a parent process. Workers are forked from it, share its memory, and are put back into their forked state between requests. See Worker pool.
  • Everything in one place. HTTPS (certificates), a control panel and dashboard, a shell, a response cache, logs and metrics.
  • Small footprint. A worker of a full CMS holds about 10 MB of private memory (measured); the dynamic pool retires idle workers.

The options you use most

OptionMeaning
--root=DIRDocument root (default ./web)
--app=DIRA Qbix application directory
--host=IP, --port=PORT, --https-port=PORTWhere to listen (defaults 0.0.0.0, 80, 443)
--socket=PATH, --socket-mode=MODEListen on a Unix socket (mode default 0660)
--workers=NPool size; default is what fits in RAM, at most 8 per core and 64, never fewer than 4
--config=FILE, --conf-dir=DIRA JSON site file; a configuration directory laid out like /etc/apache2
--preset=NAMEFramework preset: laravel, symfony, wordpress, drupal, exponential
--user=NAME, --group=NAMEWho workers run as when the server starts as root
--hotreloadWatch files and restart on change
-tTest the configuration and exit
--stop, --reloadGraceful stop, re-exec (through the pid file)
--version, --about, --copyrightRelease, build, licence

Values may be written --name=V, --name V, -name=V or -name V; flags may be turned off with --no-name.

The exponential preset

--preset=exponential runs an Exponential installation under the server with one setting. It keeps the source transform on (the legacy kernel calls header() and setcookie() in the way that depends on the SAPI) and preserves the type registries across requests; a modern framework needs neither. Without configured lists, the preset also supplies the lists of scripts, front controllers and static paths that Exponential ships, so only entry points run and only listed files are served as they are. See Engine settings.

What it serves

RequestWhat happens
A static fileSent directly, with ETag, Last-Modified, ranges, Accept-Encoding honoured (including q=0), optional precompression and an in-memory file cache that evicts the least recently used file (static files and images)
A PHP scriptRun in a pool worker; when Q.webserver.scripts is set, only the scripts listed there run by name, and everything else goes to the front controller
A directoryDirectory listings and image galleries; the document root can be listed like any other directory
A WebSocket or socket.io connectionHeld open in a long-lived process (/socket.io, /Q/socket.js)
A Server-Sent Events streamSupported (added in August 2026)
/Q/dashboard, /Q/panel, /Q/health, /Q/metrics, /Q/phpinfoThe server's own views; see control panel

The server never serves or runs a file outside the document root, even through a symbolic link (HTTP/2 and security).

Running existing applications

A compatibility layer lets Laravel, Symfony, WordPress, Drupal, Joomla and Exponential run unchanged. It rewrites the few PHP functions that do not work in a long-lived CLI process (header(), setcookie(), exit, die, session_id(); 44 functions are shimmed in all), wraps the file layer so thousands of include and stat calls per request are cheap, and resets what a request leaves behind. Details and measurements: Worker pool.

The one thing to remember: do not keep per-request state in your own statics or globals without telling the server. Globals that must survive are named in Q.webserver.keepGlobals (or --keep-globals=A,B).

Moving from Apache, nginx or Caddy

The engine ships a migration page for each. The main steps:

  1. Replace .htaccess rewrite rules by Q.webserver.frontControllers (path pattern to script), and Q.webserver.scripts / Q.web.static.paths (what may run and what may be served as a file).
  2. Put TLS in Q.web.https (HTTPS and certificates).
  3. Set --user and --group so workers do not run as root.
  4. Keep Apache or nginx in front only if you need it. Behind a load balancer that ends TLS, the application's own page cache is handed the request headers and the listener's port (release 0.0.4.35), so it finds pages stored for the public host name.

Limits

  • PHP 8.0 or later (from release 0.0.4.54; until then 8.1); the static binaries and images are built for 8.2, 8.3, 8.4 and 8.5. On PHP 8.0, AVIF image output (needs 8.1) and the dashboard's per-request memory peak (needs 8.2) are not available, and $_FILES has no full_path; RHEL 9's stock PHP 8.0 runs the engine. Details: packages and binaries and the engine's PHP 8.0 and Red Hat Enterprise Linux.
  • Windows has no fork(), so there is no pool of forked workers there; use the binary builds for Windows (packages and binaries).
  • The default event loop (stream_select) stops a pool below about 1,000 workers. Use more servers on one port (Q.webserver.reusePort, or Instances in velocity.ini) rather than more workers.
  • A POST is never retried: if a worker dies mid-request, the visitor gets a 502.

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x