On Thursday 19 March 2026 I went to the Amsterdam Java User Group, hosted by IKEA. The slides were branded âIKEA Meet Up â Amsterdam Java User Groupâ. The evening had three talks: Java virtual threads, elliptic curve cryptography, and testing a production system well enough to deploy it on a Friday afternoon. Two posts I published the same day grew out of the first two talks.

Wraps on the table, the hosts at the lectern, and the opening slide on the big screen.
Virtual Threads, by Cameron Harris
The first talk was âVirtual Threadsâ by Cameron Harris. The title slide showed a big blue IKEA bag, which suited the venue.

âVirtual Threadsâ, Cameron Harris, on the IKEA Meet Up slide template.
The slides made clear up front that this wasnât a how-to: the virtual thread API mirrors the existing platform Thread API. The talk was about why the feature exists. The âProblems weâre trying to solveâ slide listed four:
- Not a how-to. The API is the same as for platform threads, so learning the syntax isnât the hard part.
- C10K. The 2000s problem of handling more than 10,000 concurrent clients on one server.
- Asynchronous processing. Keeping the CPU busy, with a high instructions-per-cycle rate on every core, while threads wait.
- Polling. OS APIs struggled with more than about 1,000 open file descriptors, which is why epoll, kqueue and io_uring were built.
The âThread per Requestâ slide explained why the simple model is attractive and where it stops working. When code hits an I/O operation, you block the thread and let the OS scheduler wake it when the I/O completes. Thatâs simple and intuitive. But each thread needs its own stack plus OS data structures, so thereâs a limit on how many you can spawn. The workarounds have their own problems. Thread pools become a bottleneck when there are more concurrent tasks than threads. Spawning threads without a pool risks running out of memory (threads Ă stack size). And creating and destroying threads always costs something.

Thread per request: simple, but each thread brings its own stack and OS bookkeeping.
Next came asynchronous programming. A user-space event scheduler âcomes with its own set of headachesâ. The program must know where it waits on I/O. Code turns into âarbitrary bits of code glued together through eventsâ instead of a list of instructions you can read top to bottom. Cancelling a task is hard, because the cancellation logic sits outside the task. Most languages paper over this with async/await (the slide cited the EA async library). The slide also gave the speakerâs own opinion: Java didnât yet have the features that make monads pleasant to use, such as pattern matching and algebraic data types.
The closing âSome side notes on Virtual Threadsâ slide had the practical warnings. Virtual threads run on a pool of carrier threads (OS threads). By default the pool has one carrier per processor, and a system property can change that. JEP 425 covers both debugging and scheduling. A virtual thread looks like the same thread throughout its run, and that causes odd behaviour in some libraries. The slideâs example was Hibernate, which doesnât allow access from separate threads on the same session.
I wrote that last point up as why JDBC and Hibernate break with virtual threads. It covers pinning, connection pool exhaustion and session-per-thread assumptions.
My take: virtual threads remove the thread bottleneck, but the next bottleneck is usually the connection pool, so plan your capacity around that.
Elliptic Curve Cryptography Unleashed
The second talk was âElliptic Curve Cryptography Unleashed: Faster, Smaller, Strongerâ. The speakerâs âAbout meâ slide described a solution architect working on CIAM, access control, security and compliance.

Faster, smaller, stronger: the promise of elliptic curves.
The talk started from the basics: digital signature algorithms take a document, run it through a function with a private key, and produce a signature. Then came the maths slide, âThe Elliptic Curve Algorithmâ. It showed a curve function such as y² = xÂł â 3x + b, noted that itâs used in TLS, and described the scheme as hiding a point on the curve using its geometric properties: point addition (P + Q = R) and the curve group law (P + Q + RⲠ= 0). The speaker walked through the plotted curve on screen.

Point addition on the curve: the geometry behind ECDSA.
The âNIST Recommendation for Key Managementâ table made the âsmallerâ part of the title concrete. For the same security strength, ECC keys are far shorter than RSA keys:
| Security strength | Symmetric | RSA (k) | ECC (f) |
|---|---|---|---|
| 112 | 3TDEA | 2048 | 224â255 |
| 128 | AES-128 | 3072 | 256â383 |
| 192 | AES-192 | 7680 | 384â511 |
| 256 | AES-256 | 15360 | 512+ |
From there the talk moved to tokens. JSON Web Signature (RFC 7515): a JSON-based structure for secured content, made of headers (alg, key ID, web key, key set URL), a Base64URL-encoded JSON payload and a Base64URL-encoded signature. The slide pointed to jwt.io for Java libraries and the algorithms they support. Then there was a live demo: a small local web app called âECDSA and RSA digital signaturesâ. It had buttons to generate EC and RSA keys, sign a message, verify the signature, view the public keys and compare execution time.
That JWS slide is where my JSON Web Signature (RFC 7515) in Java guide started. It covers the three-part structure, the header parameters, and jjwt, Nimbus and jose4j examples.
My take: if youâre designing new token signing today, start from ECDSA or EdDSA and treat RSA as the compatibility option, not the default.
Deploying On Friday Afternoons Without Stress, by Bas Stoker
Before the last talk, a giveaway slide went up, âGift: Grow Beyond Seniorâ. It advertised an online programme that Bruno Souza, âthe Brazilian JavaManâ, gives to his mentees, with a deep dive on five paths to grow beyond senior level.
The last talk was âDeploying On Friday Afternoons Without Stressâ by Bas Stoker (the title slide read âBas Stoker // AmsterdamJUG // March 19, 2026â).

The third talk of the night: a testing story from a real production system.
The framing was the Testing Trophy, credited to Kent C. Dodds. Static analysis is the base, then unit tests, a wide band of integration tests, and end-to-end tests on top (the slide used the Dutch labels Statische analyse, Unit, Integratie and End to End). The quoted idea: you get âgreatâ value for the cost from static analysis and integration tests, and âgoodâ value from unit and e2e tests. Use them all.

The Testing Trophy, with the layers labelled in Dutch.
The case study was Dutch Railroads (NS): real-time control of all NS rolling stock, four or more agile DevOps teams, a microservices architecture, and data sources including scheduling, changes from traffic control and GPS updates. The architecture diagram showed a browser going through an ingress to a single-page frontend, a backend, Keycloak and a Postgres database. The toolset was Java, Docker, Testcontainers and Playwright, plus JUnit 5. A âContainer startup time â Problemâ slide showed where that stack gets slow.
The tests themselves are written in Cucumber, in Dutch. The example scenario âTijdsconflictâ places messages on a queue, logs in, searches for a unit, scrolls to 12:00 and checks that a delayed deployment shows up as a time conflict, with the right delay in its tooltip. A line count of the codebase showed 133 files and about 160,000 lines of code. Velocity templates made up 155,229 of those lines, Java 3,271 and Cucumber 1,603. The CI pipeline slide showed a single SystemTest job of 9m 32s that logged in to Harbor, ran the Maven tests and published screenshots, test results and a Cucumber report.

Why the system test is worth its CI minutes.
The âValue of this system testâ slide summed it up:
- An extra safety net, with all major use cases covered
- Quick validation of lifecycle-management updates, such as Keycloak upgrades
- Security testing with ZAP proxy
- Documentation generated from the tests, so itâs always up to date with the product
- Chaos testing with Toxiproxy
He ended on a light note: âMaybe thanks to these tests*, we won the NLJUG innovation awardâ, with the footnote â* This is my personal opinion :-)â. The closing slide pointed to testcontainers.com and playwright.dev.
I wrote more about this layer in System Tests: Cucumber, Playwright, and Chaos Engineering.
My take: a slow, full-stack test suite that every merge must pass is what makes Friday deploys boring. Itâs the same reasoning I use for platform upgrades on Kubernetes.