As a Software Architect, managing a software architecture that evolves to adapt to the business over the years can be a complex task. At the beginning of its life, the software architecture was scaling low and could be managed by one Back-End and one Front-End team as well as it consisted only of three layers: Single Page Application, Application Server and Database.

As the number of users and services increases, the need for a highly scalable architecture arises. At the same time, the old architecture evolves into Microservices which makes our application scalable in terms of development. In fact, each Microservices is assigned to different Back-End teams in charge of managing it with the advantage to choose and adopt autonomous releases and technologies. At this stage, the architecture is ready to add new functionalities while for the Front-End team it is difficult to manage it saving time and work. 

That’s when Microfrontends come into play. But what are exactly MFEs?

MFEs are technical and logical representation of a business subdomain in Domain-Driven Design (DDD) which allows for independent development and release of application parts. This approach avoids shared logic between subdomains and enables management by a single team.

Very important concept for applying this approach is that our architecture is domain-driven and not vice versa, so our MFEs will represent a precise subdomain. Each subdomain will be developed by a single team that will be free in choosing the right technology and methodology to implement and manage the functionality. To ensure good management of teams' work, it is important to design an architecture with very low coupling between Microfrontends (MFEs). This approach allows for independent development and release experiences.

But how can we apply the architecture and MFE? It is crucial to consider the specific context in which you are working. As always, the business domain will play a significant role in guiding the architectural decisions. The key problems that need to be addressed will be the following: Definition; Composition and Routing; Communication.


There are two techniques to define and to effectively implement the Microfrontends (MFE) architecture: Horizontal Splitting and Vertical Splitting. Let's explore each technique:

  • In Horizontal splitting, multiple MFEs are accommodated within a single view of the application. For example, a home page may consist of MFEs such as footer, header, article preview and article list. The main challenge with this approach is ensuring that teams can create a cohesive look and feel based on a common system design. However, there is a risk of creating strongly coupled components, which may deviate from the business-defined MFEs.
  • In Vertical Splitting, the application is divided into logical units based on Business subdomains. For example, there may be separate MFEs for the login page, home page, and catalog page, each designed as if it were a separate Single Page Application (SPA). This technique allows teams to have in-depth knowledge about a subdomain and facilitates the implementation of system design.

Composition and routing

Composition and routing are critical aspects of implementing the Microfrontends (MFE) architecture. There are three techniques that can be used to compose MFEs and handle routing:

  • Client-Side Composition: The app shell is responsible for merging MFEs and handling routing between them. The composition can be done at runtime or build time.
  • CDN-Side Composition: The app will be composed on the node closest to the user who requested it by using an edge-side markup language. This results in greater scalability and shorter wait time. Routing is handled at this level via urls to go from page to page.
  • Origin-Side: The app is composed using server-side rendering, with routing always handled server-side.


In the lifecycle of an MFE, there comes a point where communication is necessary. For example, an MFE may need to communicate that a user is logged in or have other MFEs perform actions. The most common communication techniques are: 

  • Data Sharing via Local Storage (such as a JWT token)
  • Parameter Passing via URL Query String
  • Parameter Passing via Events (subscribe, emit and replay mechanism)

It is important to choose the appropriate communication technique based on the specific needs and requirements of your application.

What is a Module Federation?

Module Federation is a powerful plugin introduced by Webpack in version 5.0, released in 2020. It enables the separate development of remote modules, allowing for the creation of a single application with ease. This plugin facilitates the implementation of an architecture based on the Microfrontends approach.

Let's imagine that our target business is an e-commerce site. After careful analysis, we identify three entities that can be designated as MFEs: the product list, the shopping cart, and potentially other components. The responsibility of implementing these MFEs is assigned to separate teams. Once the development of the MFEs is completed, the teams configure Webpack to make the remote modules available. 



Basically, for exported modules the Module Federation plugin exposes three properties:

  • Name which describes the name of the module.
  • Filename by default, it is named remoteEntry.js. This file acts as a manifest and provides all the necessary directions to import the remote module, including the name of the module, aliases, dependencies, and references to bundles. It is generated when the remote module is compiled, and those who use it can import it using its URL.
  • Exposes or a property that allows the paths to be made explicit via path to reach the functionality exposed by the module.

Let's now see how the team in charge of the app-shell will import the modules to merge them into one app. Firstly, we need to clarify what an app-shell is. Basically, it can be defined as a container of remote modules where part of the implementation of the MFE basics takes place

In client-side composition, the app-shell has the responsibility of not only composing the app but also providing the tools that allow the MFE to communicate and manage routing. With the proper implementation of the modules, but especially of the app-shell, we can have an architecture that is closest to the theoretical ideal of MFEs, which is low coupling, separation, and decentralization of modules managed by separate teams


The configuration of the Module Federation plugin for our app-shell has some differences. Since the app-shell's function is to import, rather than export, we use the "remotes" property for this purpose. This property defines where we can find the remoteEntry.js file that remote modules expose. The structure is straightforward: we use the name of the remote module as the key (e.g., "products" or "cart") and then indicate the module name with the "@" symbol followed by the URL. This way, our app-shell bundle will contain all the necessary information to merge our modules and create our app.


In conclusion, the Module Federation plugin in Webpack 5 has revolutionized the software architecture by allowing dynamic code loading and sharing of dependencies between different applications. By leveraging this plugin and properly configuring the app-shell, we can achieve an architecture that closely aligns with the theoretical ideal of MFEs, with low coupling, separation, and decentralization of modules managed by separate teams.

​​It's important to note that this approach is relatively new. The community is actively involved and new frameworks are being created to simplify the implementation process. Other bundlers, such as Vite, are also providing plugins to developers with some differences compared to Webpack.

It is crucial to reiterate that this approach should only be taken if it aligns with the domain's requirements. If the potential problems outweigh the benefits, it may not be the right choice. Currently, big tech companies like Dazn, Facebook, and Zalando are utilizing this approach, keeping in mind the basic principles of MFEs and applying unique solutions to ensure optimal user experience and high scalability.

Author: Marco Bartiromo, Frontend Developer @Bitrock

Read More

The recent hype surrounding Apache Flink especially after the Kafka Summit 2023 in London sparked our curiosity and prompted us to better understand the reasons for such enthusiasm.  Specifically, we wanted to know how much Flink differs from Kafka Streams, the learning curve, and the use cases where these technologies can be applied. Both solutions offer powerful tools for processing data in real-time, but they have significant differences in terms of purpose and features.

Processing Data: Apache Flink vs Kafka Streams

Apache Flink is an open-source, unified stream and batch data processing framework. It  is a distributed computing system that can process large amounts of data in real-time with fault tolerance and scalability.

On the other hand, Kafka Streams is a specific library built into Apache Kafka that provides a framework for building different applications and microservices that process data in real-time.

Kafka Streams provides a programming model that allows developers to define transformation operations over data streams using DSL-like functional APIs. This model is based on two types of APIs: the DSL API and the Processor API.  The DSL API is built on top of the Processor API and is recommended especially for beginners. The Processor API is meant for advanced applications development and involves the employment of low-level Kafka capabilities. 

Kafka Streams was created to provide a native option for processing streaming data without the need for external frameworks or libraries. A Kafka Streams job is essentially a standalone application that can be orchestrated at the user’s discretion. 

Main Differences

As previously mentioned, Flink is a running engine on which processing jobs run, while Kafka Streams is a Java library that enables client applications to run streaming jobs without the need for extra distributed systems besides a running Kafka cluster. This implies that if users want to leverage Flink for stream processing, they will need to work with two systems.

In addition, both Apache Flink and Kafka Streams offer high-level APIs (Flink DataStream APIs, Kafka Streams DSL) as well as advanced APIs for more complex implementations, such as the Kafka Streams Processor APIs.

Now, let's take a closer look at the main differences between Apache Kafka and Flink.

  1. Integrations

How do these systems establish connections with the external world? Apache Flink offers native integration with a wide range of technologies, including Hadoop, RDBMS, Elasticsearch, Hive, and more. This integration is made possible through the utilization of the Flink Connectors suite, where these connectors function as sources within Flink pipelines.

Kafka Streams is tightly integrated with Kafka for processing streaming data. The Kafka ecosystem provides Kafka Connect, which allows for the integration of external data sources as events are journaled into topics. For example, using the Kafka Connect Debezium connector, users can stream  Change Data Capture stream events into a Kafka topic. A Kafka Stream topology can then consume this topic and apply processing logic to meet specific business requirements.

  1. Scalability

 Apache Flink is an engine designed to scale out across a cluster of machines, and its scalability is only bound by the cluster definition. On the other hand, while it is possible to scale Kafka Streams applications out horizontally, the potential scalability is limited to the maximum number of partitions owned by the source topics. 

  1. Fault tolerance and reliability

 Both Kafka Streams and  Apache Flink ensure high availability and fault tolerance, but they employ different approaches. Kafka Stream delegates to the capabilities of Kafka brokers. Apache Flink depends  on external systems for persistent state management by using tiered storage and it relies on systems like Zookeeper or Kubernetes for achieving high availability.

  1. Operation

 Kafka Stream as a library, requires users to write their applications and operate them as they would normally. For example, a Kubernetes deployment can be used for this purpose and by adding Horizontal Pod Autoscaling (HPA) , it can enable horizontal scale-out.

 Apache Flink is an engine that needs to be orchestrated in order to enable Flink workloads. Currently, Flink users can leverage a Kubernetes Flink operator developed by the community to integrate Flink executions natively over Kubernetes clusters.

  1. Windowing 

Both Kafka Stream and Flink support windowing (tumbling, sliding, session) with some differences:

  • Kafka Stream manages windowing based on event time and processing time.
  • Apache Flink manages flexible windowing based on event time, processing time, and ingestion time.

Use Cases

While both frameworks offer unique features and benefits, they have different strengths when it comes to specific use cases. 

Apache Flink is the go-to choice for:

  • Real-Time Data Processing: real-time event analysis, performance monitoring, anomaly detection, and IoT sensor data processing.
  • Complex Event Processing: pattern recognition, aggregation, and related event processing, such as detecting sequences of events or managing time windows.
  • Batch Data Processing: report generation and archives data processing.
  • Machine Learning on Streaming Data: train and apply machine learning models on streaming data, enabling real-time processing of machine learning outcomes and predictions.

Kafka Stream is the go-to choice for:

  • Microservices Architectures: particularly leveraged for the implementations of event-driven patterns like event sourcing or CQRS.
  • Kafka Input and Output Data Processing: transform, filter, aggregate or enrich input data and produce output data in real-time.
  • Log Data Processing: analyze website access logs, monitor service performance, or detect significant events from system logs.
  • Real-time Analytics: data aggregation, real-time reporting, and triggering event-based actions
  • Machine Learning:  train and apply machine learning models on streaming data for real-time scoring.

Learning curve and resources

The learning curve of a technology is not always an objective fact and can vary depending on various factors. However, we have attempted to provide a general overview based on factors like resources availability and examples.

The basic concepts of Kafka Streams, such as KStreams (data streams) and KTables (data tables), can be easily grasped. While the mastery of advanced functions such as the aggregation of time windows or the processing of correlated events, may require further exploration. The official Kafka Streams documentation, available on Kafka’s website at serves as a valuable reference for learning, exploring and leveraging all its capabilities.

To get started with Apache Flink, it is recommended to learn the basic programming model, including working with data streams and data sets. Once again, mastering advanced concepts such as state management, time windows, or grouping, may require additional study and practice time. The official Flink documentation available on Confluent's website at serves as a comprehensive resource for learning and exploring as well.


To cut a long story short, Apache Flink and Kafka Streams are two open-source frameworks with their strengths and weaknesses for stream processing that can process large amounts of data in real-time. 

Apache Flink is a fully-stateful framework that can store the state of the data during processing, making it ideal for applications that require complex calculations or data consistency. Kafka Streams is a partially-stateful framework and it is ideal for applications that require low latency or to process large amounts of data. Apache Flink is a more generalized framework that can be used for various applications, including log processing, real-time data processing, and data analytics. Kafka Streams is more specific to stream processing.

We can conclude affirming that the best framework for a specific application will depend on the specific needs of the application.

Author: Luigi Cerrato, Software Engineer @ Bitrock

Thanks to the technical team of our sister company Radicalbit for their valuable contributions to this article.

Read More
Apache Flink

Nowadays organizations are facing the challenge to process massive amounts of data. Traditional batch processing systems don't meet the modern data analytics requirements anymore.  And that’s where Apache Flink comes into play.

Apache Flink is an open-source stream processing framework that provides powerful capabilities for processing and analyzing data streams in real-time. Among its key strengths, we can mention:

  • Elastic scalability to handle large-scale workloads 
  • Language flexibility  to provide API for Java, Python and SQL
  • Unified processing to perform streaming, batch and analytics computations 

Apache Flink can rely on a supportive and active community as well as offers seamless integration with Kafka, making it a versatile solution for various use cases. It provides comprehensive support for a wide range of scenarios, including streaming, batching, data normalization, pattern recognition, payment verification, clickstream analysis, log aggregation, and frequency analysis. Additionally, Flink is highly scalable and can efficiently handle workloads of any size.

During the Kafka Summit 2023, Apache Flink received significant attention, highlighting its increasing popularity and relevance. To further demonstrate the growing interest in this technology, Confluent, a leading company in the Kafka ecosystem, presented a roadmap outlining upcoming Flink-powered features for Confluent Cloud:

  • SQL Service (public preview fall 2023)
  • SQL (general availability winter 2023)
  • Java and Python API (2024)

Unleashing the power of Apache Flink: the perfect partner for Kafka

Stream processing is a data processing paradigm that involves continuously analyzing events from one or multiple data sources. It focuses on processing data in motion, as opposed to batch processing. 

Stream processing can be categorized into two types: stateless and stateful. Stateless processing involves filtering or transforming individual messages, while stateful processing involves operations like aggregation or sliding windows.

Managing state in distributed streaming computations is a complex task. However, Apache Flink aims to simplify this challenge by offering stateful processing capabilities for building streaming applications. Apache Flink provides APIs, advanced operators, and low-level control for distributed states. It is designed to be scalable, even for complex streaming JOIN queries.

The scalability and flexibility of Flink's engine are crucial in providing a powerful stream processing framework for handling big data workloads.

Furthermore, Apache Flink offers additional features and capabilities:

  • Unified Streaming and Batch APIs
  • Transactions Across Kafka and Flink
  • Machine Learning with Kafka, Flink, and Python
  • Standard SQL support

Unified Streaming and Batch APIs

Apache Flink's DataStream API combines both batch and streaming capabilities by offering support for various runtime execution modes and by doing so providing a unified programming model. When using the SQL/Table API, the execution mode is automatically determined based on the characteristics of the data sources. If all events are bound, the batch execution mode is utilized. On the other hand, if at least one event is unbounded, the streaming execution mode is employed. This flexibility allows Apache Flink to seamlessly adapt to different data processing scenarios.

Transactions Across Kafka and Flink

Apache Kafka and Apache Flink are widely deployed in robust and essential architectures. The concept of exactly-once semantics (EOS) ensure that stream processing applications  can process data through Kafka without loss or duplication. Many companies have already  adopted EOS in production  using Kafka Streams.  The advantage is that EOS can also be leveraged when combining Kafka and Flink, thanks to Flink's Kafka connector API.   This capability is particularly valuable when using Flink for transactional workloads. This feature is mature and battle-tested in production, however operating separate clusters for transactional workloads can still be challenging and sometimes cloud services with similar aimings can take over this burden in favor of simplicity.

Machine Learning with Kafka, Flink, and Python

The combination of data streaming and machine learning offers a powerful solution to efficiently deploy analytical models for real-time scoring, regardless of the scale of the operation. PyFlink, a Python API for Apache Flink, allows you to build scalable batch and streaming workloads, such as real-time data processing pipelines, large-scale exploratory data analysis, Machine Learning (ML) pipelines, and ETL processes.

Standard SQL Support

Structured Query Language (SQL) is a domain-specific language used for managing data in a relational database management system (RDBMS). However, SQL is not limited to RDBMS and is also adopted by various streaming platforms and technologies. Apache Flink  offers comprehensive support for ANSI SQL, encompassing the Data Definition Language (DDL), Data Manipulation Language (DML), and Query Language.
This is advantageous because SQL is already widely used by different professionals including developers, architects, and business analysts, in their daily work.
The SQL integration  is facilitated through the Flink SQL Gateway, which is a component of the Flink framework  and allows other applications to interact with a Flink cluster through a REST API.   This opens up the possibility of integrating Flink SQL with traditional business intelligence tools.

Additionally, Flink provides a Table API that complements the SQL capabilities by offering declarative features to imperative-like jobs. This means that users can seamlessly combine the DataStream APIs and Table APIs as shown in the following example:

 DataStream APIs and Table APIs

Flink Runtime

As mentioned, Flink supports streaming and batch processing. It’s now time to delve into the analysis of the main difference:

Streaming works with bounded or unbounded streams. In other words:

  • Entire pipeline must always be running  
  • Input must be processed as it arrives   
  • Results are reported as they become ready  
  • Failure recovery resumes from a recent snapshot    
  • Flink can guarantee effectively exactly-once results when properly set up with Kafka

Batch works only with a bounded stream. In other words:

  • Execution proceeds in stages and running as needed
  • Input may be pre-sorted by time and key
  • Results are reported at the end of the job
  • Failure recovery does a reset and full restart 
  • Effectively exactly-once guarantees are more straightforward

Flink Runtime


In a nutshell, Apache Flink offers numerous benefits for stream processing and real-time data analytics. Its seamless integration with Kafka allows for efficient data ingestion and processing. Flink's stateful processing capabilities simplify the management of distributed computations, making it easier to build complex streaming applications. The scalability and flexibility of Flink's engine enable it to handle large-scale workloads with ease. 

Additionally, Flink provides unified streaming and batch APIs, enabling developers to work with both types of data processing paradigms seamlessly. With the support of machine learning and standard SQL, Flink empowers users to perform advanced analytics and leverage familiar query languages. Overall, Apache Flink is a powerful and versatile platform that enables organizations to unlock the full potential of their real-time data.

Author: Luigi Cerrato, Software Engineer @ Bitrock

Thanks to the technical team of our sister's company Radicalbit for their valuable contributions to this article.

Read More

Artificial Intelligence (AI) is not just a buzzword; it's a transformative technology that is reshaping our reality. From work to social interactions, AI is making its mark.

In this blog post, we focus on the impact that AI is having, and will continue to have on the software development industry. We will try to answer to the crucial question: will AI replace the role of programmers entirely?

The State of the Art

To date, AIs already perform a wide range of tasks: from writing code, to conducting research in technical documentation, from revealing vulnerabilities to automating tasks from a simple prompt.

We will now mention a few of them, so that you better understand the scope of these tools. 

With GitHub Copilot it is possible to speed up the simplest and most repetitive tasks or the research phase in technical documentation with results that speak for themselves: code writing time halved, ability to perform 35% of tasks autonomously and an overall satisfaction rating of about 70%.

It turns out to be a tool - for now - that is integrated with human activity and does not aim at replacement, but upcoming evolutions could go in other directions.

Zapier, a task manager that allows to automate more or less complex tasks starting from a simple prompt, introduces a fundamental topic: using AI to automate web services that already exist through APIs, could allow even code novices to streamline, modify and customize existing Applications.
Finally, we would like to mention one last tool that is experiencing widespread adoption today: Snyk from Deepcode, an AI that can analyze an existing code and detect the presence of any vulnerabilities, thus preventing cyber attacks or malfunctions.

Risks and Opportunities

However, the hype around AI tools and OpenAI in particular seems to be overblown.

They are certainly useful tools in the design phase both in terms of organizing a project and structuring the code, but the implementation of the artifacts is something that needs to be perfected and needs even meticulous and constant review.

The greatest difficulties are encountered in giving the right input to tools: a requirement that is too narrow or too broad, without contextualizing the problem, leads to the generation of code that is difficult to reuse. 

Thinking about the AI applications in the enterprise, some of the main advantages and risks associated with the massive use of them in the programming sector become evident, as they  emerge in any other area.

A junior figure - to be considered as one with limited work experience in time -  if not properly directed by a colleague with greater seniority, can incur different risks using AI for code generation.

Settling for the first solution processed by the tool can lead to poor results or broken systems: this causes loss of confidence in the tool itself, leading to a vicious cycle of copy/paste to other sites such as Stackoverflow.

In case the developer does not have enough skills to understand the quality of the solution offered, correct or not, it prevents them from learning and growing professionally.

These and other kinds of problems are avoidable with the support of a work team that, by necessity, cannot be composed of juniors alone, and with the development of soft skills such as the ability to work in a team and continuous training.

A developer with medium/high seniority, on the other hand, can take advantage of the tools in different contexts and for different tasks. For example, he or she can benefit from AI tools to request documentation, solve common problems across projects (e.g., ORM, date management), perform code reviews with automated code production, create a test scenario, and verify that a block of code meets all the requirements of a given story.

All of this, of course, is possible by starting with a proper prompt and providing for review and a series of incremental improvements.
Indeed, it is essential to always check the quality of the solution produced in terms of conventions, nonobsolescence, and versatility of the code.


The importance of a well-built team, solid core competencies, an agile working methodology based on transparency and cooperation, and constant and open code reviews are still necessary for the success of any project.

So while the use of Artificial Intelligence tools can bring significant benefits, it is important to consider them as supporting tools and not as substitutes for human expertise and technical knowledge

It is essential to critically evaluate the results obtained, apply good development practices, and subject the generated code to human review to ensure correctness and quality.

Although some fear that in the coming years AI could completely replace developers, we are instead certain that the human figure will remain necessary. The new challenges that will emerge, especially in ethical and regulatory terms, will bring about the need for new task areas of competence for human beings.

In conclusion, AI is a powerful tool and the responsibility lies with us to ensure that we use it ethically and responsibly.

Author: Luigi Cerrato, Software Engineer @ Bitrock

Read More
Platform Engineering

Platform Engineering is one of the biggest trends that is undoubtedly here to stay, with a community and tool environment that are both expanding quickly. But there are still many unsolved questions, as with any (relatively) new trend. 

In this Blog post, we’ll try to understand the concept from scratch and answer some basic questions that both people within and outside the community are curious about.

Without further ado, here’s the essential information you should be aware of regarding Platform Engineering. Agreeing on a common definition is rather difficult; however, we can define Platform Engineering as the process of creating, developing, and maintaining the supporting infrastructure and apparatus necessary to the efficient operation of software applications.

In order to facilitate the development, deployment, and management of apps across various environments, Platform Engineering focuses on building scalable, reliable, and efficient platforms. 

Software Engineering, Infrastructure Engineering, and DevOps are all combined in Platform Engineering. Its main objective, indeed, is to provide faster software application and service delivery while also enhancing agility and flexibility in response to changing corporate needs. 

Or, in other words, to standardize processes in order to enhance the developer experience, quicken innovation cycles, and reduce the engineering organization's time to market. 

Platform Engineering allows development teams to build upon a strong foundation, which enables businesses to innovate more quickly and stay one step ahead of the competition.

The Platform team can gain a holistic understanding of developers' pain points and common difficulties inside the company by conducting user research, requesting user feedback, and getting internal buy-in from stakeholders. It can identify the features programmers require and provide a golden path that includes those answers. 

However, the Platform journey continues on. In order to ensure that developers are using the Platform and that it is actually improving developers' life, successful Platform teams maintain open lines of contact with developers and track technical KPIs.

DevOps vs. Platform Engineering

DevOps and Platform Engineering are closely related topics.

DevOps brings development and operations teams closer together, and focuses on using tools, systems and iterative processes to shorten feedback cycles. It represents a software lifecycle management’s philosophical and methodological approach that contributes to the creation of the Platform and is, in turn, one of the services delivered by it. 

Platform Engineering, on the other hand, can basically be considered as the discipline focused on the technology infrastructures and platforms’ design, development and management, on which digital services and software applications are delivered. Through the Platform, IT teams can access self-service mode for the digital assets they need, and digital business services are delivered.

Platform Engineering is also a development of DevOps, so to speak. DevOps outlines guidelines for simplifying development through automation, autonomy, and collaboration. These qualities are also crucial to Platform Engineering so the technique helps you achieve good DevOps performance.

DevOps is used as a methodology to compose Platform Engineering; one of the methodologies that, those who use Platform, find out-of-the-box. 

An Internal Corporate Service

Platform Engineering is definitely an internal corporate service that is addressed to all IT figures involved in creating digital initiatives within an organization.

Platform Engineering, in fact, can be seen as a technological-organizational moment that gives development teams access to services like monitoring and security in a "self-service" mode, which makes use of automations and the above-mentioned DevOps. 

It is a kind of large distributor of digital services within the organization, essential to any new initiative that needs access to digital assets.

Externally, however, Platform Engineering is realized in the tangible result of the application of the service built through the Platform itself. 

Impacts on IT Governance

The centralization of digital services within the Platform has significant impacts. 

First, the Platform enables considerable cost management and control, especially when it integrates elements usually external to typical corporate governance, as in the case of data centers and cloud services.

Another relevant effect resulting from Platform Engineering is the harmonization within a company's organizational set-up of all the offerings that arrive from suppliers in terms of products and services. These have to adapt to organizational security standards and methodologies for updating and maintaining infrastructure and applications. 

Therefore, IT Governance has to integrate into the Platform’s context, also embedding itself in a self-service delivered system that represents the enterprise technology asset’s backbone.

We can affirm that Platform Engineering can be seen as the answer to every CTO's dreams!


The Platform Engineering community started in 2021 with a handful of meetup groups in the USA (Austin) and Europe (Berlin). Over 10,000 Platform developers are now engaged, spread over 19 meetup groups worldwide. In light of this community movement, Platform Engineering should be taken more seriously by organizations.

And you? What are you waiting for? Discover more about Platform Engineering by listening to the latest episode of our Bitrock Tech Radio podcast, or get in contact with one of our experienced engineers and consultants!

Author: Franco Geraci, Head Of Engineering @ Bitrock

Read More

Hello, coding enthusiasts!

We will journey through the landscapes of two of the most famous programming languages in the software development world: Java and Scala. These languages are like two sides of the same coin in the JVM (Java Virtual Machine) world.

Let's dive in and explore these two captivating languages together!

Java: The Time-Tested Titan

Java, the brainchild of Sun Microsystems (now owned by Oracle), has been a pillar in the programming world for over two decades. Known for its "write once, run anywhere" philosophy , Java is everywhere – from enterprise servers to Android apps. Java's robustness, simplicity, and cross-platform capabilities have cemented its place as a reliable choice for developers.

Java is an object-oriented programming language that leans heavily on explicitness and clarity. It's like your reliable old friend – always there when you need it, and you know exactly what to expect. Developers who like control and predictability might find Java a soothing balm for their programming souls.

The extensive libraries and frameworks available for Java are one of its biggest strengths. Spring, Hibernate, Maven, and many more make Java development a breeze. Moreover, its fantastic community support and extensive documentation make troubleshooting Java relatively straightforward – there's always a fellow developer ready to lend a hand!

Scala: The Functional-Object Fusion

Scala, which stands for "Scalable Language" was introduced by Martin Odersky in 2004. It blends the best of both worlds: object-oriented and functional programming. Scala, the modern artist of the programming world, is designed to express common programming patterns in a concise, elegant, and type-safe way.

With Scala, you can write less code and accomplish more, thanks to its high-level abstractions. It's like a sleek, modern sports car – compact, efficient, and oh-so-stylish.

The Comparison: Why it's a Win-Win

Now, let's pit these two languages against each other. But remember, it's not about declaring a winner but understanding how each language can be the right tool for the right job.


Java and Scala run on the JVM, so their performance is quite similar. However, Scala's advanced features, like immutability and concurrency, might offer an edge in developing high-performance systems. But remember, performance depends more on the coder's skill than the language itself!


Java's syntax is explicit and lengthy, and it values clarity over brevity, which makes Java code easy to read and understand. On the other hand, Scala's syntax is concise and expressive. It may take a little time to get used to, but once you do, you might fall in love with its elegance!


Java is a stalwart of object-oriented programming, but with the introduction of lambdas and streams in Java 8, it has embraced functional programming concepts. Scala, conversely, beautifully merges object-oriented and functional programming paradigms. So if you're looking to explore available programming without letting go of the familiar object-oriented structure, Scala could be your ideal companion.

Too long; didn't read

In a nutshell, let's break down the comparison of Java and Scala into 20 bullet points highlighting their pros and cons:



  • Proven Stability: Java has been around for over two decades, and its stability is time-tested.
  • Wide Adoption: Used by millions of developers worldwide, resulting in a vast community and extensive resources.
  • Clear and Explicit Syntax: The protracted nature of Java makes it easy to understand, reducing ambiguity.
  • Robust Libraries and Frameworks: Spring, Hibernate, and Maven make development easier.
  • Platform Independence: The "write once, run anywhere" philosophy ensures cross-platform compatibility.
  • Excellent Documentation: Comprehensive and extensive documentation is available.
  • Job Market: Due to its wide adoption, there are many job opportunities for Java developers.
  • Gradual Introduction to Functional Programming: With Java 8 and beyond, developers can explore functional programming concepts.


  • Verbose Syntax: Java requires more lines of code to accomplish tasks, which can lead to boilerplate code.
  • Slower to Adapt Modern Features: Java tends to be slower in adopting new programming concepts.



  • Functional and Object-Oriented: Scala beautifully merges object-oriented and functional programming paradigms.
  • Concise Syntax: Scala code is typically shorter than equivalent Java code, leading to increased productivity.
  • Advanced Features: Scala has modern features like traits, case classes, and implicit.
  • Great for Concurrency: Immutable data and first-class functions make Scala an excellent choice for concurrent and reactive applications.
  • Java Interoperability: Scala can seamlessly interoperate with Java code and libraries.
  • Powerful Tools: Scala has powerful tools like SBT and frameworks like Akka.


  • Steep Learning Curve: Scala's advanced features and concise syntax might be hard to grasp for beginners.
  • Smaller Community: Compared to Java, Scala's community is smaller, meaning less support and resources.
  • Less Job Market: There are fewer job opportunities for Scala developers compared to Java.
  • Complexity: The flexibility and power of Scala can lead to overly complex code if not used judiciously.


The choice between Java and Scala should be based on your project requirements, your team's skill set, and your personal preference. They are both powerful tools in their own right and understanding their strengths and weaknesses will help you make an informed decision.

Happy coding!

Author: Franco Geraci, Head Of Engineering at Bitrock

Read More

A few months ago, we began an incredible journey into the world of Java through a compelling retrospective written in collaboration with Danilo Ventura, Senior Software Engineer at Bitrock.

Enjoy the fourth and last episode following below!

In 2014 a revolutionary new version of Java arrived. All versions of Java are backward compatible, meaning that sources generated with a new version of Java are executable on older Java VMs. This revolutionary version of Java 8 allows for a leap in functional languages. So come many new tools such as streams, lambda expressions, optionals to write more functional code using both the object-oriented paradigm and the functional paradigm. Java 8 was really a milestone because it gave birth to new constructs and many Java developers took years to get used to it.

The first Java application framework like Spring Boot

From now on, Java is used to create services and for web applications. The first Java frameworks begin to emerge to quickly create applications that provide Rest Json services. For convenience, we will mention only the most important one: Spring Boot. The latter is based on a leaner library that was precisely Spring (launched in 2016) and made developers’s life easier allowing not to use the complex EJBs but to create JARs able to self-execute, without installing a server and running it.


Cloud, Container and Docker

It is precisely with this in mind that a new revolution takes place, that of the cloud and containers. Before, servers and their maintenance were 'in house' - just think of banks and insurance companies; right around this time, the concept of Cloud was born mainly with giants such as Amazon, Google, and Microsoft providing the necessary tools to create 'machines' on the web where you can install everything you need to run your website or web application. In this way, all the maintenance of the '(virtual) machine' is entrusted to the Cloud Manager.

The other major aspect is the container, since it changes the way applications are distributed. The distribution, indeed, is now published through a container that can be basically seen as a 'machine' with an operating system inside and a container executor called Docker that guarantees the security and functionality of the application.


“Write once, run anywhere (WORA)” or not?

All of this shakes the concept and motto of Java: "Write once, run anywhere". If the application can be distributed in a container with the preferred operating system, what are the advantages of still using Java? Indeed, there are none and this is precisely the reason why new and alternative languages emerged such as Rust and Google's GO whose container takes 5 milliseconds to start - instead of Java, which needs 30 seconds.

It seems like Java in this Cloud Native world would have no future. Actually, it was not true. Along comes a super revolutionary technology in Java: the GraalVM, which allows native code to be generated from bytecode of any type. So a bytecode starting from a source of any type - Java, C - is created for a special virtual machine which is precisely the GraalVM capable of generating an executable file for a given operating system. Why is it revolutionary? Java can be used to create a container with an executable in it that can start in times comparable to services written in GO.

Java continues to move forward by adapting to new frameworks that allow services to be written directly cloud-native. For instance, one noteworthy framework is Quarkus, which allows the generation of cloud-native containers that can run on Docker or any container orchestrator.

The new frontier of Web 3.0

We are on the threshold of Web 3.0, and the new frontier is the blockchain-based web. Perspectives are starting to change and new architectures are being released: server-side, there will no longer be a single server managed by a platform. Just to give you an example: YouTube is run by Google, owned by Google, and the videos that are uploaded are on Google's servers as well as owned by Google.

With Web 3.0, the perspective changes, since the platform is not owned by a single owner anymore, but distributed on the blockchain.

In line with the times and needs, the Web continues to evolve while facing many difficulties and uncertainties. How will Java adapt to this new type of architecture? We will see! In the meantime, we can say that we are not standing still but moving with this evolution; there are already several pieces of evidence, such as new framework libraries (e.g. Spring) that allow interaction with popular blockchains.

We have come to the end of this fourth and final episode of the retrospective dedicated to Java. We thank Danilo Ventura for sharing his valuable insights on Java technologies and wrapping up 20 years of web history.

You can also read the firstsecond and third parts. Follow us on LinkedIn and stay tuned for upcoming interesting technology articles on our blog!

Read More
Mobile App

Mobile applications are softwares that run on mobile devices such as smartphones, tablets, etc. Developing a mobile app is a great way to have your clients always connected one tap away from your business. With a tool like this you could open new roads to help your customers with your product anywhere they are, create more engagement and understand better what they like most by collecting some analytics.

Do you want to learn more about our Mobile App Development solutions? Visit our dedicated page and submit the form. One of our consultants will get back to you right away!

Not every app is built in the same way

A mobile app can be built in different ways, it all depends on what the software aims to do and it is never an easy choice nowadays. Let's see what kind of mobile app development approaches exist at the moment and understand better their main differences by looking at pros and cons of each.


A native mobile app is a software built for a specific platform, iOS or Android, by using the tooling system provided from Apple or Google respectively.

These kinds of apps are the most powerful, the code is optimized to work on a specific operating system in order to achieve the best performance. By using the native tooling systems with their latest updates the UI/UX can be developed to follow all the styling guidelines provided by Apple and Google more easily for the developers. This can still be the best option for apps that need to do a lot of computation or require a deep implementation of the system APIs like Bluetooth, GPS, NFC, and so on.

Looks everything cool but... where is the catch? Well, unfortunately these kinds of apps are the most expensive since both iOS developers and Android developers are needed to build and maintain the two apps completely separately and different from each other.

iOS developers use XCode as the main IDE (integrated development environment) and the main languages used are Swift and Objective-C, meanwhile for Android apps developers can use Android Studio writing Kotlin and Java code.


In the last few years a new technology came from JetBrains and it is called Kotlin Multiplatform (KMP).

This is a new way of developing apps where the developers can share part of the code written in Kotlin between the iOS and the Android app keeping the code native thus with the same performances (or so) of a native implementation. Usually developers share some Business Logics and the communications with servers or local storage and leave the UI/UX development natively. Of course depending on the project, more or less modules should be shared between the two apps. A good architect will choose the best structure to build the project.

From an android point of view the app development is close to a native app while for the iOS developers the UI will be written in Swift, as always, but it will connect to some logic written in Kotlin.

The Kotlin Multiplatform framework will compile both apps on native code for you. Looks like magic right? Yes, it does, but reality is not all about pros with KMP. You will still need both iOS and Android developers to build and maintain the apps, plus the framework is still new and there are some technical downsides with this approach. Depending on the project, a native approach could turn out to be even less expensive than a KMP one, especially when it comes to keep updated the project itself.

We at Bitrock love to explore new technologies, we already used this framework on some projects, and we're looking forward to seeing if this will be the new standard of mobile app development in the future.



Cross-Platform apps are built in a different way compared to the Multiplatform ones. At the moment there are two main frameworks on the top level of a cross-platform approach: Flutter and React Native. With both frameworks the developers can write the code only once for the two apps, usually reducing the cost and time to market for the clients. React Native is the older one, it was started back in 2015 by Facebook and made a huge step forward in Cross-Platform development reaching performances close to a native app. After that a new player joined in 2018: Flutter, built by Google. It rapidly gained popularity because of its stunning performances and for how quick it is to build beautiful UIs with that framework.

Under the cover, React Native is close to ReactJS, the UI is built with component blocks and the main language is Javascript. On the other hand, Flutter has widgets to compose the UI and the main language is Dart. Each RN UI component is chained to a native one for the specific platform, meanwhile for Flutter each component is drawn from scratch by the Flutter team and rendered on a canvas with Skia Graphics Engine.

They are both really great frameworks to build cross-platform apps with performances really close to the native implementation but with less expenses. 

The downsides of both frameworks are related to your project needs. These are technologies relatively new and we cannot say for how long they will be updated and maintained. If the framework will be shut down, it will not be as easy as the approaches above to work with deprecated technologies or, in the worst case, restore the app with a native implementation by rewriting it from scratch.

Our feeling is that these kinds of approaches are here to stay and they are and will be the best choice for a lot of beautiful projects.

Flutter and React Native

WebApp and PWA

These are the kind of websites that act like mobile apps when opened from a browser on a mobile device.

PWA (Progressive Web Application) are WebApp with superpowers, they can be used to interact with part of the device hardware as well and can perform different things based on which device is running the software.

Usually they are not available on the App Store and Play Store, even though for Android something started moving with TWA.

These kinds of apps are usually written with web languages: HTML, CSS and Javascript, like a normal website. At the moment these are the apps with the lowest performance but they are easier to maintain and release since there are no updates needed throughout the official stores, sometimes app updates can be tricky to achieve and with these solutions we avoid that completely.

PWA (Progressive Web Application)


Native vs Multiplatform vs Cross-Platform vs WebApp.

What is the best development approach for your app in 2023?

“It depends!” as developers love to say.

In choosing the right app, a lot will rely on your project, needs, goals, target audience and mostly on the budget you decide to invest.

We at Bitrock would love to hear more about your project idea to support you with all our expertise and experience on this jungle of code and frameworks. In the meantime, we will keep us updated on what's coming next and we are excited to see how the future of mobile apps will look like.

Special thanks to the main author of this article: Emanuele Maso, Mobile Developer at Bitrock. 

Do you want to learn more about our Mobile App Development solutions? Visit our dedicated page and submit the form. One of our consultants will get back to you right away!

Read More
Java 3

A few months ago, we began an incredible journey into the world of Java through a compelling retrospective written in collaboration with Danilo Ventura, Senior Software Engineer at Bitrock. We can move on with our narrative by depicting what happened in the mid- and late-2000s as well as highlighting the developments of Java with the advent of Web 2.0 .

Back in early 2005 there was a major revolution that kicked off what has been called Web 2.0. What is it? Web 2.0 is the revolution in the computer industry caused by the move to the internet as a platform. It’s an improved version of the first world wide web, characterized specifically by the change from static to dynamic or user-generated content and also the growth of social media like, for instance, the first one that was YouTube to publish video. Starting from these years, the web begins to transform itself into a container of platforms.

Ajax and JSON

What was the technical evolution that allowed this to happen? New browsers like Firefox and Chrome took advantage of a new technology called Ajax (Asynchronous JavaScript and XML) which allowed for asynchronous calls. What does it mean? Browsers launch a request and while the response arrives another request can be launched.  All this makes web pages more interactive and faster. Pages populate as long as requests are completed. It also changes the very structure of web applications because you no longer have to provide the entire page but only the data.
The web application development changed and new frameworks were based on Javascript. Between 2005 and 2010 came the first JavaScript library for web applications distributed as a free software: jQuery. Later came more powerful frameworks for open source web applications such as AngularJs up to Angular 2 and React JS.

Hence, server-side applications become just data providers. The new interchange of data between client/server applications was based on JSON, which stands for JavaScript Object Notation. This was an open standard file format and data interchange format that used human-readable text to store and transmit data objects consisting of attribute-value pairs and arrays (or other serialisable values).

Java and the Mobile Operating Systems

In 2008, the first commercial Android device was unveiled: this was another important moment for Java. Android is an operating system that basically runs programs that are written in Java and compiled by a Dalvik virtual machine that is able to take this Java code and turn it into the bytecode that is then executed by the Android operating systems. The competitor Apple developed iOS, a parallel proprietary operating system, while Google based everything on Android and the open source language of Java. One more time, Java played a major role as a programming language to write mobile applications.

Criticism of Java

In 2010, the largest database software and technology company Oracle acquired Sun Microsystem, consequently Java became property of Oracle. What changed? Java became a proprietary language and only the latest version remained free. For older versions you still have to go through Java distributors. 

Later the Java programming language and Java software platform were criticized by the developer communities for design choices, including the implementation of generics, forced object-oriented programming. New high-level programming languages have been designed to fully interoperate with the Java Virtual Machine version. We can mention Scala released in 2004 as well as Kotlin in 2011.

We have to wait until 2014 for another revolutionary version of Java.

You can also read the first, second and forth parts. Follow us on LinkedIn and stay tuned for upcoming interesting technology articles on our blog!

Thanks to Danilo Ventura for the valuable contribution to this article series.

Read More
Java | Part 2 | 2000s

A few months ago, we began an incredible journey into the world of Java through a compelling retrospective written in collaboration with Danilo Ventura, Senior Software Engineer at Bitrock. We can move on in our narrative by depicting what happened in the early 2000s.

From Java Server Pages to eXtensible markup language

We saw that Java servlets allowed higher degrees of interactivity and dynamicity in web design. Yet, a significant limitation still existed. Servers could only produce static HTML pages, with no variable elements. Inside a Servlet you had to write all the code of each html page putting together variable data (for example coming from a DB) and static data. 

To simplify the process, in 1999 Sun Microsystems released the first version of a new revolutionary technology: Java Server Pages (JSP).  With JSP  pages it was possible to insert in a HTML page, scripting section parts in java language, creating a “JSP page”. JSP was translated into Servlet and then compiled. With Java Server Pages and servlets led to the birth of server-side pages. This means that pages were no longer static (steady and immutable as website creators thought them): on the contrary, they were dynamically generated on the server side, using the JSP as a template with dynamic contents inside. 

We’ve come to the early 2000s: during these years, the first Java frameworks to write web applications emerge. The most relevant ones we must mention are Velocity (a template engine, rather than a framework), Struts and then Struts2. Tools like these were the first attempts to apply the M.V.C. pattern in web application development. Struts and Struts2 were based on XML (“eXtensible markup language”), which was designed to be a human and machine-readable markup language for handling data transport. XML was born as an exchange format for data but it was also (ab)used as a configuration language.

The Enterprise Java Beans and the Web 1.0 age

The evolution of distributed applications still lacked and it could be achieved only thanks to another Java technology: Enterprise Java Beans (EJB). We can now describe EJB as an architecture for setting up program components, written in the Java programming language, that run in the server parts of a computer network that uses the client/server model.

EJB was a very powerful, complex and also widely used technology. Enterprise Java Beans were based on application servers: we are no longer talking about simple servers or servlet engines. In order to execute EJB, developers required application servers that had an entire substrate (called EJB Container) thanks to which, whenever the application was deployed, a wide array of runtime components was generated, creating an actual ecosystem that allows the application to interact with server resources. Many Software houses, at that time, had its own product of EJB Application Server: WebSphere from IBM, Weblogic from BEA Systems (later acquired by Oracle), and, of course, were present open source products too such as JBoss, Apache TomEE and GlassFish.

Developing applications for this technology was rather complicated, IT since professionals had to deal not only with code writing operations, but also with repetitive actions: launching programs, packaging the application in a certain way, having the correct library dependencies for the projects and so on. All these tasks were done manually: as you can imagine, the chance of error was particularly high. Moreover, it was a huge waste of time (that could be dedicated to development) for developers to generate all these packages that would be deployed on application servers.

This led to the creation of new tools able to solve these needs, starting from Ant. Ant was a very innovative tool since, always through XML, it was possible to write procedures to be executed inside the Java world. Through an Ant script in XML, you could run a sequence of operations, such as copying and filing out files, moving some parts to a specific folder, creating a Java archive from that folder and moving it elsewhere. It was thus possible to automate a number of tasks.


Ant arrived in 2002, followed by Maven in 2004 (which is still used nowadays). Last but not least, Gradle appeared around 2012. Maven, now, allows a java developer to manage all dependencies and the lifecycle of its application in a standard way. All these tools, by solving a series of issues, have been essential to guarantee Java survival, otherwise it would have gone extinct.

In the early 2000s - the Web 1.0 age - there were some alternatives to Java. Some examples? PHP, C#, and Microsoft .NET (the Microsoft technology for building Web Applications in Windows environments).

This was also the glorious time of other technologies that were presumed to have an explosive success. Starting from Adobe Flash. At the time, if you didn’t have a Flash animation on your website, you were basically considered a loser! For this reason, Adobe launched this technology that allowed programmers to create, thanks to a language mainly based on Javascript and XML, a code that was executed from the browsers through a proper HTML tag that was generated.

Java 5

2004 was a breakthrough year, marked by the arrival of a version of Java that is still considered game-changing for many aspects: Java 5. Java 5 showed some new features, i.e. generics (taken from C language), annotations, enumerations, varargs, static imports. Sun Microsystem’s programmers and the Java communities, indeed, realized that in those years evolutions were fast-paced and, if they wanted to remain competitive and make Java a modern language, they would have to introduce additional features.

Not being a static language and continuously evolving through time, was the trump card that made Java survive in the long run. Through the implementation of new features, developers' needs have always been responded to. Java, as a matter of fact, is open-source: all Java developers can download the sources and can manifest within the community which features they would like to be implemented. Even then, the developer community, when talking about the implementation of new features, put it up to the vote.

In those years service-based architectures also began to evolve and companies started realizing that the mainframe was likely to fade away soon. However, there was the need within companies to maintain data sharing available through services.

At this stage, we begin to have problems and questions, like for instance, how do we exchange data? Which language do we use to make different technologies interact with each other? How do we restructure data? Then XML becomes established as an exchange language allowing to structure and to control data.

The first service-oriented architecture (SOA) arose based on a SOAP protocol able to exchange data among multiple technologies and in different formats. Between 2006 - 2009, new solutions, for more complex situations, were implemented, such as, for instance,  enterprise service bus (ESB), that resolves in a brilliant way the point to point communication problem for different software technologies.

Elements of SOA, by Dirk Krafzig, Karl Banke, and Dirk Slama (Source:Wikipedia)

Java is part of this revolution and is no longer just a language for web application, but is evolving to follow the new requirements of the server world.

You can also read the first, third and forth parts. Follow us on LinkedIn and stay tuned for upcoming interesting technology articles on our blog!

Thanks to Danilo Ventura for the valuable contribution to this article series.

Read More