Skip to content

Latest commit

 

History

History
193 lines (107 loc) · 6.61 KB

File metadata and controls

193 lines (107 loc) · 6.61 KB

Migration from JMeter

Why rebuild a framework that already worked?

This document reflects on the transition from the original JMeter-based framework (Version 1) to the current k6 implementation (Version 2). Rather than comparing two tools, it explains the engineering decisions, trade-offs and lessons learned while rebuilding an existing performance testing framework.


Introduction

The migration to k6 was not driven by technical limitations of JMeter.

Instead, it was initiated by an company decision to standardize development around the JavaScript/TypeScript ecosystem.

Performance testing tooling was expected to follow the same direction.

At first glance, translating an existing test plan into another tool sounds straightforward.

In reality, it became an opportunity to reconsider several years of accumulated design decisions.

Instead of performing a one-to-one migration, I chose to redesign the framework from scratch while preserving the ideas that had already proven successful in production.


Why Version 2 Exists

Version 1 grew under significant time pressure.

We need it yesterday kind of pressure.

Like many long-lived projects, it accumulated compromises that were perfectly reasonable at the time but gradually became obstacles as new requirements appeared.

The framework remained functional and continued to produce reliable performance test results, yet extending it became increasingly difficult.

Rather than carrying those limitations into a new platform, I decided to treat the migration as an architectural reset.

The objective became simple:

Preserve the engineering experience even if implementation would drastically change.


What I Wanted to Preserve

Despite moving to an entirely different execution model, many concepts from the original framework deserved to survive.

Among them were:

  • realistic business workflows instead of isolated HTTP requests
  • reusable helper scripts
  • custom parsing logic
  • reporting automation
  • infrastructure monitoring
  • business-oriented metrics
  • extensive custom scripting

Several JSR223 Listeners, parsers and utility components had already demonstrated their value during real performance investigations.

Those ideas were worth keeping, even if their implementation changed completely.


What JMeter Did Surprisingly Well

JMeter is frequently perceived as a GUI tool.

For simple test plans - yes.

However, once Java and JSR223 components become part of the project, JMeter turns into something much closer to a scripting framework running on top of the JVM.

Having access to the Java ecosystem opens possibilities that are difficult to replicate elsewhere.

Among the advantages I appreciated the most were:

  • full support of Java instead of Groovy (with nuances ofc)
  • unrestricted custom logic
  • direct access to Java libraries
  • mature ecosystem
  • flexible listeners and processors

Complex business logic often became surprisingly straightforward because there were very few artificial limitations imposed by the platform itself.


What Became Harder in k6

Moving to k6 introduced an entirely different execution model.

The most significant difference is that virtual users are intentionally isolated.

Each virtual user executes independently without shared memory.

While SharedArray and setup() provide mechanisms for sharing static initialization data, they cannot be used for mutable runtime state.

For stateless API testing this is rarely a problem.

For stateful scenarios involving multiple cooperating actors, it changes the architecture considerably.

Several capabilities that were trivial inside JMeter suddenly required dedicated infrastructure.

Examples include:

  • synchronizing multiple virtual users
  • sharing identifiers between actors
  • coordinating asynchronous/parallel workflows
  • matching agents with conversations

Instead of treating these as limitations to work around inside individual scenarios, Version 2 introduces a dedicated synchronization layer using Redis.

This approach increases architectural complexity but keeps individual scenarios significantly cleaner.

More details are available in:

Synchronizing Virtual Users


What Became Easier in k6

Although scenario synchronization became more complicated, project organization improved considerably.

Everything inside the framework became regular source code.

Development happens entirely inside an IDE rather than inside a graphical test plan.

This offers several practical benefits.

Large-scale refactoring becomes easier.

Navigation between modules becomes straightforward.

Version control diffs become meaningful.

Debugging benefits from the tooling available for modern JavaScript projects.

One issue I repeatedly encountered in the original JMeter framework was the gradual growth of large Groovy scripts.

Eventually those scripts became difficult to maintain inside the GUI.

The natural solution was to move them into external JAR libraries.

While this improved organization, it also introduced a slower development cycle involving compilation, packaging and importing before changes could be tested.

Working with plain JavaScript modules removes much of that friction.


Architecture Changes

The migration highlighted a more important lesson than choosing one tool over another.

Different execution models naturally encourage different architectures.

The framework introduced:

  • a dedicated synchronization layer
  • an independent reporting service
  • clearer separation between load generation and reporting
  • modular scenario organization
  • explicit communication between components

Ironically, some limitations of k6 encouraged a cleaner overall architecture.

Responsibilities that previously lived inside one large test plan became separate systems with clearly defined boundaries.


Lessons Learned

Looking back, the migration taught me that rebuilding a framework is fundamentally different from translating one.

Instead of trying to force k6 to behave like JMeter, I didn't fight it.

Learned its capabilities and limitations, then designed a ways to achieve my goals.

This is almost always the best approach.


Which Framework Would I Choose Today?

Honestly, I probably wouldn't have much choice.

In most companies, the performance testing stack is decided by organizational standards rather than individual preference.

For me, the framework is simply another engineering constraint.

Every tool has strengths and limitations. The job is to understand them and build a maintainable solution around them.

Version 1 and Version 2 solve the same problems using different execution models.