Jamie Balfour

Welcome to my personal website.

Find out more about me, my personal projects, reviews, courses and much more here.

Jamie Balfour'sPersonal blog

mod_zpe was first written in 2024 and has been pretty decent since. Its only letdown was one of ZPE's biggest weaknesses - it needed a fresh start every time it was required. Now with the latest update and ZPE 1.14.4's new ZPE-PM, it's finally possible to get exceptional performance from ZPE.

ZPE-PM is a daemon that runs YASS code via a socket. That means that there is no start-up cost associated with running code. This makes responses very quick - almost instant. 

ZPE is even more integrated into VWS than into Apache, offering an easy-to-manage installation. But at least now it works with Apache too.

ZPE-PM is the latest feature to make it into ZPE 1.14.4, and it's a major addition. 

ZPE-PM or ZPE Process Manager works like PHP-FPM (FastCGI Process Manager). ZPE-PM is designed to run as a daemon process, much like ZPE Lite (more on that later). 

One of the biggest limitations of traditional scripting setups is that every request starts from scratch.

  • Load runtime
  • Parse code
  • Execute
  • Tear everything down

That’s fine for small scripts, but as things grow, it becomes inefficient — and harder to scale.

So I built ZPE-PM.

ZPE-PM is a long-running process that executes ZPE scripts over a socket connection.

Instead of launching ZPE for every request, you:

  1. Start ZPE-PM once
  2. Send it execution requests over a socket
  3. Receive results (or live output)

It acts as a bridge between:

  • clients (CLI tools, web servers like VWS)
  • and the ZPE runtime

ZPE Lite is now, well, really lite. Using the zpe -l command to run the Lite mode is easy. You simply provide a file name to run through ZPE-PM (ZPE-PM must be running), and a host and port number are optional. By default, the host is localhost, and the port is 8940. 

You can also communicate with ZPE-PM with Python, C#, or any programming language that supports sockets. 

It's very fast. Processing with ZPE 1.14.4 has become considerably faster overall, so the Standard Algorithms went from 650ms to around 300ms in the latest update. But ZPE-PM makes the whole process really fast, and the newly improved ZPEC caching system comes in really handy for further performance improvements. Running a script once caches the byte codes for the next run. But not only that, ZPEC is designed for low-latency internalised communication, so requests are very lightweight, adding only around 7ms of overhead.

ZPE 1.14.4 is a big update. It mainly focuses on performance but also on integration with VWS.

First performance. This is big. Running the Standard Algorithms library in ZPE 1.14.3 took an average time of ~600ms. With ZPE 1.14.4, the mean time is now ~350ms. This is a massive improvement. ZPEX has gone from 30ms to 23ms to run the same library too. 

VWS has recently been revisited, so ZPE's support for VWS has been improved. New session variables, cookies and much more have been added to ZPE. ZPE's web performance has also been improved. As well as this, in addition to the YASS Web Pages (ywp) files you can create, you can now also compile these to YASS Executable Pages (yep) files for up to 5x faster processing. Nice.

ZPE now has a new --tools option for special tools in ZPE. ZPE --install now actually installs ZPE. ZPEC has been improved too, offering much better and faster performance than before. LAMEX3 comes to ZPE - 'improved' by ChatGPT (although performance has occasionally been lower than LAMEX2, I am working to ensure it is consistently faster than X2).

ZPE 1.14.4 will be out very soon, as I am just adding the finishing touches. 

VWS 1.1.3 is a big update with many new performance improvements and features.

VBench

Part of Velocity Web Server's growth has been adding tools to make managing a web server easier than ever. VBench, a new benchmarking tool, continues this philosophy. It works much like Apache Benchmark and is designed to be a drop-in replacement for quickly running benchmarks on any operating system, with a single command in VWS.

Much like ApacheBench, VBench sends many concurrent requests to a web server to test how well it handles them. VWS, on average, can handle 180 requests per second on a simple PHP page, whereas Apache is closer to 75 per second (though this is not an official number yet), as I'll need to do more rigorous testing later.

VBench is something I've wanted to make for a long time, and now I have. 

Web Assets

Web Assets are a special type of asset that can be cached by the web server. For example, let's say you host many websites on your web server, and all of these websites use React. Well, rather than specifically copying React to each of these websites, just use the Web Assets tool - firstly install the asset (React) and then on each of the pages requiring React, just write and VWS will provide it for you. And it's quick too. 

Web Asset Bundles

Web Asset Bundles are even more interesting and useful. These combine multiple assets into a single request before sending them to you, reducing the number of requests. Same idea, but instead of the word asset, we use bundle: . It's fast, and it's powerful. 

The most recent benchmarkings

I benchmark VWS frequently using Apache Bench. The command used is ab -n 10000 -c 40 url. I do this for both Apache and VWS and run the same file on the same server. I then get ChatGPT to look at the results from both of them and summarise. Thanks to some real performance improvements, VWS pulls ahead of Apache in all benchmarks carried out. Here's what ChatGPT had to say:

VWS performed slightly better than Apache in this test. Apache handled 2544.69 requests/sec with a mean request time of 15.719 ms, while VWS handled 2670.49 requests/sec with a mean request time of 14.979 ms. Both completed 10,000 requests at concurrency 40 with 0 failed requests.

Latency was also a bit better on VWS. The median request time was 14 ms for VWS versus 15 ms for Apache, and the 99th percentile was 24 ms for VWS versus 36 ms for Apache. That suggests VWS had slightly better tail latency in this run.

Apache showed a lower mean connect time, but VWS showed a lower mean processing time. Apache’s mean connect time was 5 ms versus 8 ms for VWS, but Apache’s mean processing time was 10 ms versus 7 ms for VWS. Overall total mean time still favoured VWS at 15 ms versus 16 ms for Apache.

Apache transferred more total bytes, 4,010,000 versus 3,020,000 for VWS, while both transferred the same HTML payload, 1,310,000 bytes. That suggests Apache was sending more header overhead, while VWS was leaner on the wire.

So the overall finding is that, for this particular internet-facing test at concurrency 40, VWS was competitive with Apache and slightly faster overall, with lower average latency, better tail latency, and no failed requests.

Next steps

I had given up on VWS until last month. But now look at it. It's nearly a fully-fledged web server.

VWS is nearly production-ready. The introduction of benchmarking tools has allowed me to test how well VWS handles multiple requests, and it does pretty well. I have no concerns about VWS being able to deliver what's needed on scale, but I want to get it right.

Additionally, ZPE has been getting a lot of attention over the last four months, with this month and last month focused on the new features in VWS. 

Velocity Web Server (VWS) has been getting more and more features for over a week now. Over the last few days, VWS has gained quite a lot:

  • POST and GET (query string) parameter values
  • Sessions and session variables
  • Cookies
  • Headers
  • RESPONSE and REQUEST parameters
  • Virtual hosts - multiple domains on one server
  • A Control Server (used to receive control signals)
  • MIME type support
  • Keep alive
  • Redirects

Additionally, ZPE's performance has improved. ZPE now supports compiled YASS Web Pages known as YASS Executable Pages (.yep). This improves page loading performance considerably. 

VWS will be released at the end of this month, alongside ZPE 1.14.4.

As the title suggests, this evening I had a major breakthrough with Velocity Web Server, introducing TLS support. This was one of the biggest barriers to the development of VWS back in 2023, but now it's back on track, and the server is getting better and better.

I am now looking into virtual hosts and adding automatic Let's Encrypt certificate issuance. 

VWS performance, particularly for static files, is exceptional and very, very fast. In addition, if you end up going with ZPE and YASS Web Pages, you'll see the huge performance gains you can get from a solid web server built on modularity.

As the title says, I'm now actively working to improve Velocity Web Server and make it better than before. And over the last few weeks of development, I can happily say that it's already on track for massive improvements.

This week's updates include the addition of cookies, session variables (which run in memory, not storage), post and query string parameters, built-in Python web handling, TLS, and much tighter integration with ZPE/YASS through the YASS Web Page (YWP) standard. 

Not only that, but VWS is fast, portable and very easy to use. 

A simple java -jar vws.jar --install command installs VWS, similar to the command in ZPE 1.14.4, so you can then just run VWS with vws. And running VWS is as simple as vws -p portNumber. Simple. TLS will be improved further in the next few versions, but you can already enjoy it in version 1.1. 

VWS can now also be embedded as a server in a Java project, handling all the heavy lifting of a web server. 

Future versions aim to have a JavaScript and TypeScript runtime to support running JavaScript backends, new routing support, virtual addresses and so much more, it's on route to being a really powerful web server.

ZPE 1.14.3 is another big update, and it's coming at the end of this week. 

x509_pem_fingerprint

There is a new predefined function in ZPE, x509_pem_fingerprint, previously available only through the new zpe.lib.security library. 

In addition, the direct inclusion of X.509 fingerprinting means that ZPE now supports different types of plugins and libraries. Some libraries are what are called trusted libraries - they are signed by me. Then there are untrusted libraries. ZPE will soon block these on their first load, but they can still be used after approval. These untrusted libraries will also not have the same access in sandbox mode, with restrictions on system files and being limited to the sandbox folder. In addition, certain activities, such as reflection, executing commands, and networking, will be banned. If the sandbox is disabled, they are free to do what they want. Sandbox is now enabled by default in ZPE 1.14 and later.

Stricter lockdown procedures

Lockdown is a feature added in July 2025 that allows ZPE to run in a safe mode, ensuring that certain features cannot be run or loaded. Lockdown is stricter than before in ZPE 1.14.3, as plugins will not load at all during lockdown.

Further module improvements

Modules also received a major update. When modules were first introduced, they worked fine with a main function, unless the code was compiled using the YASS Compiler in ZPE and saved to an executable file. Now that's all changed. During compilation, the main function is identified and referenced, thus ensuring that main functions within a module load correctly.

Plugin and library updates

With all the work I've been doing on plugin and library security over the last few versions, this update further improves how libraries are integrated into ZPE.

Libraries have deep access to ZPE, and they are core to expanding its possibilities even further. However, in recent versions, due to the number of plugins and libraries available to ZPE on the rise, and the inclusion of trust checks within them, plugin loading has become a burden on startup times. As a result, I realised that plugins and libraries should be loaded asynchronously on startup. This, however, causes another issue: if a library is loaded after a program is run in ZPE, it will throw an error. To combat this, I've added an additional form of loading - using the already included import command:

import "zpe.lib.sqlite"

This means you can force the loading of a plugin right there and then, and if it's already been loaded asynchronously, the import statement does nothing. Nice!

Check out the new plugins

Several new plugins are under development. These new plugins, which are currently mostly libraries, are designed to extend ZPE's functionality and were one of the key goals when ZPE was first conceptualised. A couple of the new libraries are:

libMSAccess, libSQLite, libUI, libSerial, libSystemInfo, libMQTT, libMySQL

Plugins can now be added via ZULE (ZPE Uploads, Libraries and Extensions) package manager (which is getting an update in the next version) using the --plugins option:

--zule install --plugins

You can find out more about the libraries and plugins available on my GitHub page, where I share all the source code and the latest trusted builds.

New compiler feature

Previous versions of ZPE did not support using the arrow operator (->) to access an object after a function call, such as print(get_wikipedia_reference("USB")->title). This has been a problem for a while, but after a five-minute look at the compiler, it was an easy fix. So you can now probe the result of a function with an arrow operator.

ZPE 1.14.2 has been released this weekend. The new version brings a ton of new enhancements including the ability to view variables at certain points in the program through proper debugging tools that offer step over and execution pausing - not just termination.

ZIDE v.0.1.0-alpha has also been released, and this is the first version to be properly released. You can download the JAR from my GitHub and the individual binaries from my website (Linux coming soon).

ZIDE is not like ZPE in the sense that ZIDE is still in very early days. Each time a new binary is built, it will automatically be uploaded to my website for downloading. GitHub also will continue to feature release tags for each version. You can see the full source code for ZIDE on my GitHub as well.

ZPE 1.14.2 brings three major features.

Universal template parsing

Template parsing was introduced some time ago, but was released only in January 2026 with ZPE version 1.14.1. In the latest release, version 1.14.2, template parsing is available anywhere, including in parameters and return values.

Scope blocks

Many languages have scope blocks, and now YASS does too. They are nice and easy to use as well. Simply using the double brace syntax ({{ }} or the block syntax (block . . . end block), you can create an isolated scope block:

YASS
// Everything here runs inside the implicit GLOBAL function

$total = 100
print("Start total: " & $total)

block

  // This variable exists ONLY inside the block
  $total = 25
  print("Inside block: " & $total)

  // Blocks can still see outer variables
  $discount = 10
  $total = $total - $discount
  print("After discount: " & $total)

end block

// Block variables are discarded
print("End total: " & $total)

Variable scoping

Additionally, variables declared as private in a function are scoped to the containing function and no longer modify parent or global variables, allowing safer encapsulation while preserving YASS’s simple scoping model.

Powered by DASH 2.0