Dynatech is a unique tech company in many ways, as it employs over 250 technical people to support all the global brands in the Dyninno Group. Founded in 2016, the company utilizes modern technologies to develop the ever-expanding product portfolio while ensuring the high quality of the code.
We interviewed Jurijs Saveljevs, Lead Software Engineer, and Viesturs Teivans, Tech Lead, to find how they have set up their tech stack and daily work. The interview covers topics including the benefits of Node.JS & Typescript, what mistakes Dynatech has made when choosing technologies and how they approach data-driven decision-making.
🔵 To start at the beginning, what does the company Dynatech do exactly?
Jurijs: Dynatech is a global business center based in Riga, Latvia. Among others, we provide IT services and solutions for all the businesses within the Dyninno Group, consisting of three divisions: Travel, Entertainment and FinTech. There are many independent businesses within the conglomerate, and Dynatech is the unified technology company powering them. Mainly by IT services but also competencies in marketing, HR, project management, etc.
🔵 How is the work divided between different teams in Dynatech?
Viesturs: The work is divided mostly by product. Within each of these three areas of the Dyninno Group, we have specific products with specific teams. Sometimes teams have multiple projects at hand because some of them only need to be maintained. It’s also possible to migrate between them, for example, if a person is interested in a technical problem that involves a specific product.
We also have people like Jurijs who work on R&D. This is a shared team that supports the infrastructure of all our products. For example, they pick the new technologies and research the best practices for implementing them. That helped us a lot in migration to Kubernetes and automated pipelines.
🔵 Can you describe a bit what projects you are working on these days? What do you like the most about them?
Viesturs: I’m developing a new flight search product which consists of several Node.js applications. In addition to writing the code, I’m also very involved in managing the code quality to keep it easily maintainable and ensure that we have proper unit tests. A lot of it is automated, but we still make sure that people use this automation consistently, and we don’t end up with spaghetti code.
We’ve had several major refactors during the project, and those were mostly pretty easy. For example, we have changed the internal data structure for the search functionality two times, which is an enormous refactor for all the services that need to operate on it. I make sure that things like that go smoothly.
Jurijs: I’m working more on infrastructure and applying best practices to the application development flow. We’re currently moving to orchestrated environments, mostly Kubernetes, which means we run multiple clusters for multiple products in various Kubernetes installations. Mostly on AWS EKS, but we are also experimenting with DigitalOcean. We have some exposure in Russia, where we use Yandex.Cloud, and we are also researching some Asian cloud providers. So I’m into orchestration and bootstrapping applications for that.
The second thing I’m working on is application metrics, so whenever there is an anomaly in how the product or runtime behaves, we get alerted. And the third is ensuring the continuous deployment for our applications, including making sure that every application is built and containerized correctly, and doesn’t have any known security vulnerabilities or obvious bugs that we can catch with static code analysis.
🔵 What principles do you follow when choosing new technologies?
Jurijs: We indeed have some key factors that we value in technology choices. One of them is open-sourceness because whenever something doesn’t fit, you can identify the issue and improve it. We actively contribute to some open-source projects, especially to the infrastructure stuff where there aren’t many administrative tools for the job. We like Node.js & TypeScript especially because of the self debugging and profiling. These problems were solved a long time ago, and you don’t need to worry about them.
Viesturs: In the case of Node.JS, another great strength is the mature and highly active community. If you have an issue with some package, it’s likely that the solution already exists. Yes, it still might not be optimal, and you may need to contribute, but overall, it speeds up the development a lot.
🔵 Have you had any significant strategic mistakes when building your technology stack?
Jurijs: The major misdirections were probably related to how we make critical decisions. The first thing that comes to mind was the tendency to split everything up into microservices. We followed that trend too aggressively and spread the services too thin, this is now known as the nano service anti-pattern. Fortunately, we managed to fix it by reunifying some functionality, but we definitely had that problem back in the day.
The other misdirection was the tendency to build custom solutions for the things that already existed. It’s called the “not invented here” syndrome, which sometimes happens in huge companies. At some point, we were at around 300 tech tools, some of which were probably built just because folks wanted to try something new. Or there was one feature lacking, so they copied the entire product plus the one missing feature. We have fixed this issue by introducing a formal process for technology decisions.
Viesturs: We also have sometimes chosen the wrong technology for the project. One unhappy project is running on Hack, which is a version of PHP by Facebook. The major challenge with it is the lack of community, which means you have to write everything yourself. Even something as simple as ORM to use your database correctly. Although the ORM exists, it has issues, probably because someone somewhere didn’t have time to finish it properly. It’s a super weird scenario that wouldn’t happen with any normal open-source ORM. And in the end, Hack doesn’t solve much other than what PHP already does.
🔵 How do you ensure the quality of your codebase? How does your tech stack help you with the ease of refactoring?
The next thing is this decoupling of code, the modularity. During my time here, I have introduced a principle that if your application uses an external service, it has to have its own service around it. Therefore, if you change the API or the application requirements, you can simply create a bit of middleware that translates the input to whatever your application needs.
And finally, unit tests. All the interfaces won’t save you with major refactors, like changing the data structure for a service that’s already running. It may look like it’s working on the surface, but then some response comes back as the wrong type, etc. Once you have the unit tests, they can actually show you what’s working or not. And then you have to either update the test, if the data structure has changed, or update the code.
🔵 Let’s talk about testing for a moment. How have you organised the testing major updates, so both the developers and business people stay happy?
Viesturs: For the business people, it’s the metrics. Are there enough requests? Do the clients react how we expected? If they don’t, then is it a bug? So monitoring is the big thing when we’re in production.
In the testing environment, we have automated unit tests for the Node.js applications. They run in the QA pipeline, and if something does not pass, we don’t merge it. The major releases are also tested semi-automatically by our QA people. They check things like if the user does something, does the correct log message happen? Do we get the correct change database?
Jurijs: We also use some functional tests in production to ensure the quality of service. Periodic tests, targeted at the production environment, are performing the users’ usual workflows. In the case of an online ticket agency, we might search for flight tickets or a destination. And we can verify if we find what we need. We have such tests for the vital functions of every service.
We also use stress and load testing to monitor known bottlenecks and search for unknown ones. We run the stress tests mostly on the production environment in off-peak hours. These tests don’t run periodically, but we perform them on-demand after notable component changes.
🔵 How did you come up with the data streaming approach for the microservices? What is it, and how do you use it currently?
Viesturs: I think it’s a pretty popular solution currently. The idea behind the data stream is that Redis is handling the data transfer between services. One of the advantages is reducing strain on the network. If you have numerous services trying to communicate with each other, you put enormous pressure on the network. Even in the case of internal services, there might be gigabytes of data flying here and there. People sometimes tend to ignore those internal processes as they don’t go over the internet, but if we have 300+ services that talk with each other, then the situation becomes pretty bad.
The second advantage is ensuring that the data ends up where it needs to. Because the data stays in the Redis, any service that needs it can get it. In some ways, it’s insurance against processing errors. For instance, if a service has an error and needs rebooting, then after coming back up, it can simply check the data and continue where it left off. In terms of the actual code, it’s also more understandable with data streaming. The data stream is usually observable, and the service that called it already has the context for maintaining the data.
Jurijs: Data streaming allows us to predictably design system communication. In a classical RPC flow, a service would send a request and then get results in return. But data streaming guarantees that we can provide the results. Also, you can ping results any time or share them across the systems as long as everyone is aware of the DTL. It allows very efficient contracts for spreading data across the system.
🔵 How do you use the data in daily discussions?
Jurijs: We genuinely believe in data-driven decision-making. In any argument, whether it’s tech-related or it’s business-related, the person who wins is the one who has numbers that are gathered correctly and prove his opinion. If we don’t already have the data, then we follow a pretty scientific process to collect it. For example, we might set out to test a hypothesis that building X will improve Y in some way. If you share this belief in data and the scientific method of doing things, you fit into our team very well.
Viesturs: And I guess most programmers probably do! (Laughing)
🔵 And finally, what type of developers would fit into the Dynatech team the best, in your opinion?
Jurijs: It might sound naive, but the answer is that we need people who share our values. We believe in quality: If you invest time in better design, optimisation or automation, from our experience, it usually pays off. We are searching for folks who believe the same.
Check out Dynatech’s open positions on MeetFrank:
- Senior PHP Developer
- Java Engineer (Security Team)
- Senior Node.js Developer
- Technical Support Specialist (Helpdesk)
- Team Leader (Software Engineering)
Viesturs: I absolutely agree. We value people who are passionate and aim for quality in the code they deliver. Also, we expect that people can support their opinions with data. When it comes to tech choices, the “I want to try something new and cool” approach is not good enough. We have to pick the tools that are best for solving a specific problem.
For example, just before the interview, we were arguing with Jurijs about tech choices. We invite these arguments because the best solutions arise from the creative conflict. The idea is that you can bring your own opinion, but you also have to support it with a use case.