On June 19, 2025, I went to PiterJS #79 in St. Petersburg. The evening had a refreshingly unglamorous theme: not how to ship the next feature, but how to maintain what has already been built — monitoring, deployment, and refactoring.
The program matched that theme closely. Pavel Shlykov spoke about improving an old monolith, Alexander Panfilov covered FrontOps, and Igor Antonov talked about web application performance metrics. I left with practical notes on all three topics.
The unexpected part was the Q&A. I ended up winning two prizes for asking the best questions during the sessions. It was a small thing, but it became the most memorable detail of the evening because it reinforced why I still value technical meetups in person: you can do more than consume a prepared talk. You can test your understanding while the people who presented the material are still in the room.
The useful theme was maintenance, not novelty
Frontend events can easily become a parade of new frameworks, new APIs, and new abstractions. PiterJS #79 was more grounded. Its announced theme was about supporting software that already exists.
That matters because most engineering work happens after the first successful release. A legacy monolith is not automatically a bad system, and “modernization” does not automatically mean rewriting everything. The practical question is usually narrower: which constraint is hurting the system now, and what change reduces that pain without creating more risk than it removes?
That is also why the three talks fit together well. Refactoring changes the code. FrontOps changes how the frontend is built, packaged, delivered, and operated. Performance work changes how we measure the result. Those are different layers of the same problem: keeping a real system understandable and controllable after it has grown.
FrontOps is wider than a Dockerfile
One of my notes from the meetup was about implementing FrontOps with Docker. The important distinction is that Docker is a tool, not the definition of FrontOps.
Frontend responsibility does not necessarily end when npm run build succeeds. In a production system, someone still has to think about reproducible builds, how artifacts are packaged, how configuration reaches the application, how releases are rolled back, how caching behaves, and how failures are observed. Containers can make some of that work more predictable, but they do not replace the operational decisions themselves.
This is a useful correction to a common mental model: a successful build proves that a build completed. It does not prove that the application will be deployed correctly, behave correctly in production, or be easy to recover when something goes wrong.
Performance starts with deciding what “slow” means
The performance talk was especially practical in how it framed measurement. Its announced scope included the factors that affect loading speed, different frontend performance metrics, ways to quantify “slow,” and even the question of why optimization is not always necessary.
That last point is easy to underestimate. “Make it faster” sounds objective, but without a metric and a user-visible problem it can turn into expensive guesswork. A useful performance process starts by defining what is actually slow, measuring it, identifying the bottleneck, changing one relevant thing, and measuring again.
A metric is not the user experience by itself, but it gives the discussion a shared unit. Without measurement, performance work can become a collection of technically impressive changes with no clear evidence that they improved the problem that mattered.
The Q&A changed the value of the meetup for me
I could have watched recordings and collected links later. What I could not reproduce as easily was the interaction around the talks. Asking a good question forces you to compress your uncertainty into something specific enough for another engineer to answer.
Winning two prizes was fun, but the more useful lesson was simpler: showing up prepared to participate gives an offline meetup much more value than treating it like a live YouTube playlist.
A strong technical question usually has context and a constraint. Instead of “What is the best architecture?”, it is more useful to ask what trade-off changes when a team cannot rewrite a legacy system, when deployment must remain backward-compatible, or when a performance metric improves without a corresponding user-visible benefit.
That does not mean every question needs to be clever. It means the question should help expose assumptions, boundaries, or failure modes.
What I would take into the next technical meetup
- Know why a talk matters to you. Write down one real problem or uncertainty before the session starts.
- Separate the speaker’s experience from your own system. A useful case study is evidence, not a universal recipe.
- Ask about trade-offs. “When would you not use this?” is often more revealing than “Which tool is best?”
- Capture one follow-up action. A note is more useful when it points to something to verify, test, or read after the meetup.
- Do not confuse a convincing talk with production proof. Architecture, deployment, and performance decisions still have to be validated in your own environment.
What stayed with me
I do not want to overstate what one meetup can change. I did not leave PiterJS with a universal architecture recipe, and a good talk does not replace documentation, profiling, testing, or production data.
What I did leave with was more concrete: useful notes on modernizing a legacy monolith, FrontOps with Docker, and web performance measurement; two prizes from the Q&A; and another reminder that local developer communities are worth showing up for.
Recordings can preserve the presentation. The part that is hardest to archive is the conversation around it.