[DevoxxUK2025] Concerto for Java and AI: Building Production-Ready LLM Applications
At DevoxxUK2025, Thomas Vitale, a software engineer at Systematic, delivered an inspiring session on integrating generative AI into Java applications to enhance his music composition process. Combining his passion for music and software engineering, Thomas showcased a “composer assistant” application built with Spring AI, addressing real-world use cases like text classification, semantic search, and structured data extraction. Through live coding and a musical performance, he demonstrated how Java developers can leverage large language models (LLMs) for production-ready applications, emphasizing security, observability, and developer experience. His talk culminated in a live composition for an audience-chosen action movie scene, blending AI-driven suggestions with human creativity.
The Why Factor for AI Integration
Thomas introduced his “Why Factor” to evaluate hype technologies like generative AI. First, identify the problem: for his composer assistant, he needed to organize and access musical data efficiently. Second, assess production readiness: LLMs must be secure and reliable for real-world use. Third, prioritize developer experience: tools like Spring AI simplify integration without disrupting workflows. By focusing on these principles, Thomas avoided blindly adopting AI, ensuring it solved specific issues, such as automating data classification to free up time for creative tasks like composing music.
Enhancing Applications with Spring AI
Using a Spring Boot application with a Thymeleaf frontend, Thomas integrated Spring AI to connect to LLMs like those from Ollama (local) and Mistral AI (cloud). He demonstrated text classification by creating a POST endpoint to categorize musical data (e.g., “Irish tin whistle” as an instrument) using a chat client API. To mitigate risks like prompt injection attacks, he employed Java enumerations to enforce structured outputs, converting free text into JSON-parsed Java objects. This approach ensured security and usability, allowing developers to swap models without code changes, enhancing flexibility for production environments.
Semantic Search and Retrieval-Augmented Generation
Thomas addressed the challenge of searching musical data by meaning, not just keywords, using semantic search. By leveraging embedding models in Spring AI, he converted text (e.g., “melancholic”) into numerical vectors stored in a PostgreSQL database, enabling searches for related terms like “sad.” He extended this with retrieval-augmented generation (RAG), where a chat client advisor retrieves relevant data before querying the LLM. For instance, asking, “What instruments for a melancholic scene?” returned suggestions like cello, based on his dataset, improving search accuracy and user experience.
Structured Data Extraction and Human Oversight
To streamline data entry, Thomas implemented structured data extraction, converting unstructured director notes (e.g., from audio recordings) into JSON objects for database storage. Spring AI facilitated this by defining a JSON schema for the LLM to follow, ensuring structured outputs. Recognizing LLMs’ potential for errors, he emphasized keeping humans in the loop, requiring users to review extracted data before saving. This approach, applied to his composer assistant, reduced manual effort while maintaining accuracy, applicable to scenarios like customer support ticket processing.
Tools and MCP for Enhanced Functionality
Thomas enhanced his application with tools, enabling LLMs to call internal APIs, such as saving composition notes. Using Spring Data, he annotated methods to make them accessible to the model, allowing automated actions like data storage. He also introduced the Model Context Protocol (MCP), implemented in Quarkus, to integrate with external music software via MIDI signals. This allowed the LLM to play chord progressions (e.g., in A minor) through his piano software, demonstrating how MCP extends AI capabilities across local processes, though he cautioned it’s not yet production-ready.
Observability and Live Composition
To ensure production readiness, Thomas integrated OpenTelemetry for observability, tracking LLM operations like token usage and prompt augmentation. During the session, he invited the audience to choose a movie scene (action won) and used his application to generate a composition plan, suggesting chord progressions (e.g., I-VI-III-VII) and instruments like percussion and strings. He performed the music live, copy-pasting AI-suggested notes into his software, fixing minor bugs, and adding creative touches, showcasing a practical blend of AI automation and human artistry.
Links:
[RivieraDev2025] Dhruv Kumar – Platform Engineering + AI: The Next-Gen DevOps
At Riviera DEV 2025, Dhruv Kumar delivered an engaging presentation on platform engineering, a discipline reshaping software delivery by addressing modern development challenges. Stepping in for Silva Devi, Dhruv, a senior product manager at CloudBees, explored how platform engineering, augmented by artificial intelligence, streamlines workflows, enhances developer productivity, and mitigates the complexities of cloud-native environments. His talk illuminated the transformative potential of internal developer platforms (IDPs) and AI-driven automation, offering a vision for a more efficient and secure software development lifecycle (SDLC).
The Challenges of Modern Software Development
Dhruv began by highlighting the evolving responsibilities of developers, who now spend only about 11% of their time coding, according to a survey by software.com. The remaining time is consumed by non-coding tasks such as testing, deployment, and managing security vulnerabilities. The shift-left movement, while intended to empower developers by integrating testing and deployment earlier in the process, often burdens them with tasks outside their core expertise. This is compounded by the transition to cloud environments, which introduces complex microservices architectures and distributed systems, creating navigation challenges and integration headaches.
Additionally, the rise of AI has accelerated software development, increasing code volume and tool proliferation, while supply chain attacks exploit these complexities, demanding constant vigilance from developers. Dhruv emphasized that these challenges—fragmented workflows, heightened security risks, and tool overload—necessitate a new approach to streamline processes and empower teams.
Platform Engineering: A Unified Approach
Platform engineering emerges as a solution to these issues, providing a cohesive framework for software delivery. Dhruv defined it as the discipline of designing toolchains and workflows that enable self-service capabilities for engineering teams in the cloud-native era. Central to this is the concept of an internal developer platform (IDP), which integrates tools and processes across the SDLC, from coding to deployment. By establishing a common SDLC model and vocabulary, platform engineering ensures that stakeholders—developers, QA, and security teams—share a unified understanding, reducing miscommunication and enhancing actionability.
Dhruv highlighted three pillars of effective platform engineering: a standardized SDLC model, secure best practices embedded in workflows, and the freedom for developers to use familiar tools. This last point, supported by a Forbes study from September 2023, underscores that happier developers, using tools they prefer, complete tasks 10% faster. By fostering collaboration and reducing context-switching, platform engineering creates an environment where developers can focus on innovation rather than operational overhead.
AI as a Catalyst for Optimization
Artificial intelligence plays a pivotal role in amplifying platform engineering’s impact. Dhruv explained that AI’s value lies not in generating code but in filtering noise and optimizing practices. By leveraging a robust SDLC data model, AI can provide actionable insights, provided it is fed high-quality data. For instance, AI-driven testing can prioritize time-intensive issues, streamline QA processes, and run only relevant tests based on code changes, reducing costs and feedback cycles. Dhruv cited examples like AI agents identifying vulnerabilities in code components or assessing risks in production ecosystems, automating fixes where appropriate.
He also introduced the Model Context Protocol (MCP), an open standard that enables applications to provide context to large language models, enhancing AI’s ability to deliver precise recommendations. From troubleshooting CI/CD pipelines to onboarding new developers, AI, when integrated with platform engineering, empowers teams to address bottlenecks and scale efficiently in a cloud-native world.
Empowering Developers and Securing the Future
Dhruv concluded by emphasizing that platform engineering, bolstered by AI, re-engages all actors in the software delivery process, from developers to leadership. By normalizing data across tools and providing metrics like DORA (DevOps Research and Assessment), IDPs offer visibility into bottlenecks and investment opportunities. This holistic approach not only secures the tech stack against supply chain attacks but also fosters a culture of productivity and developer satisfaction.
He encouraged attendees to explore CloudBees’ platform, which exemplifies these principles by breaking free from traditional platform limitations. Dhruv’s call to action urged developers to adopt platform engineering practices, leverage AI for optimization, and provide feedback to refine these evolving methodologies, ensuring a future where software delivery is both efficient and resilient.
Links:
[PyConUS2025] Lightning Talks Friday Afternoon: Community Practice, Creative Tools, and Critical Reflection
Lecturer
This session was hosted by community organizers who facilitated a rapid series of five-minute presentations by conference attendees. The speakers included Rodrigo Girão Serrão, a frequent contributor of educational lightning talks and author of Python-focused writing at mathspp.com; Laís Carvalho, associated with the Humble Data beginner workshops; Cheuk Ting Ho, Python Software Foundation Fellow, Humble Data co-founder, and developer advocate formerly with JetBrains; Quang Vu, a software engineer exploring computer vision for personal skill improvement; Meagen Voss, core team member of the Wagtail CMS project; Will Lachance, presenting solar energy modeling; Amanda Lundberg, addressing live captioning; Thomas Weiss, working with historical weather data for fire risk; Tom Rutherford, examining low-level process creation; Cody Maloney, investigating file-object lifecycle issues in the standard library; Anthony Shaw, Microsoft Python advocate and creator of the CSnakes embedding project; and Trey Hunner, Python Software Foundation Fellow, educator, and founder of Python Morsels. The collective nature of the session reflects the participatory ethos of PyCon lightning talks.
Abstract
The Friday afternoon lightning talks at PyCon US 2025 assembled a diverse sequence of short presentations that spanned pedagogical advice, beginner education, practical tooling, hobbyist computer vision, web-application failure modes, environmental modeling, accessibility practice, scientific data pipelines, language runtime internals, resource management, cross-runtime interoperation, and ethical reflection on emerging technologies. Taken together, the talks illustrate how the Python community simultaneously cultivates entry-level participation, technical craftsmanship, and critical awareness of systemic consequences.
Cultivating Participation and Beginner Pathways
Rodrigo Girão Serrão opened the session with a meta-presentation on the craft of lightning talks themselves. He emphasized that the format’s five-minute constraint, combined with stage lighting that often obscures the audience, lowers the barrier for first-time speakers. Content need not be restricted to Python; prior memorable talks had covered beer, music, puzzles, and vocal exercises. Practical guidance included sparse slides with large fonts, awareness of the hosts’ escalating applause cue, and the primacy of personal enjoyment as a predictor of audience engagement. The talk functioned both as invitation and as modeling of the form it advocated.
Laís Carvalho followed with an invitation to the Humble Data workshop, a Hatchery-program offering scheduled for the following Sunday. Humble Data provides structured, notebook-based introductions to Python and data-science fundamentals—Jupyter, pandas, matplotlib—for absolute beginners. Carvalho noted that the workshop had been delivered internationally and that completion of even a single notebook would be rewarded with conference swag. The presentation underscored the conference’s commitment to lowering technical thresholds and expanding the circle of participants who feel entitled to contribute.
Cheuk Ting Ho then addressed a lighter but recurrent conference phenomenon: the accumulation of sponsor swag. Drawing an analogy to Untappd, the beer-review application, Ho described Oscar Swag (a playful coinage), a web service that allows attendees to photograph, catalog, comment upon, and rate free merchandise. Built rapidly with the assistance of generative tools and hosted at a personal domain, the project demonstrated both the ease of contemporary web development and the social value of shared knowledge about durable versus ephemeral conference gifts. The talk illustrated how informal community tooling can emerge spontaneously from shared experience.
Technical Craft, Hobbies, and Runtime Awareness
Quang Vu presented a computer-vision pipeline developed to improve personal archery form. Consistency of body position matters more than absolute accuracy; therefore Vu employed recent Meta models (SAM and related segmentation networks) to isolate the archer’s silhouette, compute centroids, and align video frames despite changes in clothing or camera angle. Pixel-wise comparison proved brittle; segmentation-based alignment proved more robust. Remaining limitations—centroid precision, model sensitivity to rear viewpoints, temporal alignment of differing motion speeds—were candidly acknowledged, and the speaker invited collaboration. The project exemplified the transfer of professional computer-vision techniques into recreational skill acquisition.
Meagen Voss recounted a production incident on a personal Wagtail CMS site. Insertion of an animated goat GIF, intended as humorous illustration of the “testing goat” metaphor from Harry Percival’s test-driven-development literature, exhausted the memory of a modest DigitalOcean droplet running Gunicorn and Nginx. The administrative interface became partially inaccessible. Diagnosis revealed that the image-processing pipeline, combined with limited RAM, produced cascading failures. The anecdote served as a cautionary tale about resource assumptions in content-management systems and as an advertisement for Wagtail’s subsequent evolution and its upcoming virtual conference.
Will Lachance described a model for estimating solar-panel energy yield. Using historical irradiance and weather data, the system produced hourly forecasts and visualized expected production. The project’s modest computational cost and the speaker’s willingness to open the code illustrated the accessibility of domain-specific scientific computing within the Python ecosystem.
Amanda Lundberg’s talk, “Captioner is Human,” highlighted the labor of live captioning. The presentation reminded the audience that the service is performed by skilled humans rather than fully automated systems, reinforcing the ethical and practical necessity of supporting professional captioning at technical events.
Thomas Weiss demonstrated a predictive model for fire-weather conditions drawn from historical Remote Automated Weather Station (RAWS) data. Features such as temperature, relative humidity, and wind were used to flag stations meeting critical thresholds. The system ran at negligible cost and updated hourly, showing how publicly available environmental data can be operationalized for public-safety awareness.
Tom Rutherford examined the semantics and hazards of os.fork. Prior to recent Python versions, the default process-creation method on POSIX systems copied the parent’s address space while leaving only the forking thread alive in the child. Active locks or other thread-local state therefore produced deadlocks. The progressive deprecation of fork as default—first on macOS, later universally—reflects a deliberate prioritization of safety over the convenience of shared memory. Rutherford’s examples clarified why production codebases had long avoided the construct and why the language is migrating toward spawn-based isolation.
Cody Maloney reminded the audience of the necessity of closing file-like objects. A community-reported bug triggered by a gzip write into a BytesIO under Python 3.13 exposed an older reference cycle introduced when buffered writers were adopted for performance. The cycle caused the buffer to be closed before residual data were flushed, producing an exception only after a diagnostic print was added. Subsequent point releases repaired the cycle, and Python 3.14 will emit an explicit warning for unclosed gzip objects containing unwritten data. Maloney advocated the consistent use of context managers and, where appropriate, the higher-level pathlib helpers that encapsulate correct resource management while also enabling future performance optimizations.
Interoperation, Ethics, and Systemic Thinking
Anthony Shaw presented CSnakes, a project that embeds a Python interpreter inside .NET processes. Motivated by the comparative scarcity of mature machine-learning libraries in the C# ecosystem, CSnakes uses static builds of Python, parses type-annotated Python functions, and generates corresponding C# bindings. Complex signatures—including generators of nested tuples—are automatically marshaled. Asynchronous Python functions become awaitable C# methods, and free-threaded Python is supported so that .NET thread-pool workers can invoke Python concurrently. The demonstration with Hugging Face Transformers illustrated how a few hundred lines of generated C# can expose sophisticated Python pipelines as ordinary .NET methods, lowering the cost of polyglot architecture.
Trey Hunner closed the session with a comparative reflection on large language models and industrial animal agriculture. Both domains exhibit substantial negative externalities—environmental, health-related, and ethical—yet neither is likely to disappear through individual abstention alone. Systemic problems, Hunner argued, require systemic remedies rather than moralized individual restraint. The talk cautioned against gatekeeping rhetoric that shames tool users and invited the community to channel critical energy toward institutional and regulatory change. The analogy, deliberately provocative, reframed heated debates about generative AI as questions of collective design rather than personal purity.
Collectively the Friday lightning talks demonstrated the breadth of activity that five minutes can contain: pedagogical invitation, tool building, personal instrumentation, failure analysis, scientific modeling, language-runtime vigilance, cross-language embedding, and ethical systems thinking. The session itself modeled the participatory culture it celebrated.
Links:
[DevoxxFR2025] Boosting Java Application Startup Time: JVM and Framework Optimizations
In the world of modern application deployment, particularly in cloud-native and microservice architectures, fast startup time is a crucial factor impacting scalability, resilience, and cost efficiency. Slow-starting applications can delay deployments, hinder auto-scaling responsiveness, and consume resources unnecessarily. Olivier Bourgain, in his presentation, delved into strategies for significantly accelerating the startup time of Java applications, focusing on optimizations at both the Java Virtual Machine (JVM) level and within popular frameworks like Spring Boot. He explored techniques ranging from garbage collection tuning to leveraging emerging technologies like OpenJDK’s Project Leyden and Spring AOT (Ahead-of-Time Compilation) to make Java applications lighter, faster, and more efficient from the moment they start.
The Importance of Fast Startup
Olivier began by explaining why fast startup time matters in modern environments. In microservices architectures, applications are frequently started and stopped as part of scaling events, deployments, or rolling updates. A slow startup adds to the time it takes to scale up to handle increased load, potentially leading to performance degradation or service unavailability. In serverless or function-as-a-service environments, cold starts (the time it takes for an idle instance to become ready) are directly impacted by application startup time, affecting latency and user experience. Faster startup also improves developer productivity by reducing the waiting time during local development and testing cycles. Olivier emphasized that optimizing startup time is no longer just a minor optimization but a fundamental requirement for efficient cloud-native deployments.
JVM and Garbage Collection Optimizations
Optimizing the JVM configuration and understanding garbage collection behavior are foundational steps in improving Java application startup. Olivier discussed how different garbage collectors (like G1, Parallel, or ZGC) can impact startup time and memory usage. Tuning JVM arguments related to heap size, garbage collection pauses, and just-in-time (JIT) compilation tiers can influence how quickly the application becomes responsive. While JIT compilation is crucial for long-term performance, it can introduce startup overhead as the JVM analyzes and optimizes code during initial execution. Techniques like Class Data Sharing (CDS) were mentioned as a way to reduce startup time by sharing pre-processed class metadata between multiple JVM instances. Olivier provided practical tips and configurations for optimizing JVM settings specifically for faster startup, balancing it with overall application performance.
Framework Optimizations: Spring Boot and Beyond
Popular frameworks like Spring Boot, while providing immense productivity benefits, can sometimes contribute to longer startup times due to their extensive features and reliance on reflection and classpath scanning during initialization. Olivier explored strategies within the Spring ecosystem and other frameworks to mitigate this. He highlighted Spring AOT (Ahead-of-Time Compilation) as a transformative technology that analyzes the application at build time and generates optimized code and configuration, reducing the work the JVM needs to do at runtime. This can significantly decrease startup time and memory footprint, making Spring Boot applications more suitable for resource-constrained environments and serverless deployments. Project Leyden in OpenJDK, aiming to enable static images and further AOT compilation for Java, was also discussed as a future direction for improving startup performance at the language level. Olivier demonstrated how applying these framework-specific optimizations and leveraging AOT compilation can have a dramatic impact on the startup speed of Java applications, making them competitive with applications written in languages traditionally known for faster startup.
Links:
- Olivier Bourgain: https://www.linkedin.com/in/olivier-bourgain/
- Mirakl: https://www.mirakl.com/
- Spring Boot: https://spring.io/projects/spring-boot
- OpenJDK Project Leyden: https://openjdk.org/projects/leyden/
- Devoxx France LinkedIn: https://www.linkedin.com/company/devoxx-france/
- Devoxx France Bluesky: https://bsky.app/profile/devoxx.fr
- Devoxx France Website: https://www.devoxx.fr/
[KotlinConf2024] DataFrame: Kotlin’s Dynamic Data Handling
At KotlinConf2024, Roman Belov, JetBrains’ Kotlin Moods group leader, showcased Kotlin DataFrame, a versatile library for managing flat and hierarchical data. Designed for general developers, not just data scientists, DataFrame handles CSV, JSON, and object subgraphs, enabling seamless data transformation and visualization. Roman demonstrated its integration with Kotlin Notebook for prototyping and a compiler plugin for dynamic type inference, using a KotlinConf app backend as an example. This talk highlighted how DataFrame empowers developers to build robust, interactive data pipelines.
DataFrame: A Versatile Data Structure
Kotlin DataFrame redefines data handling for Kotlin developers. Roman explained that, unlike traditional data classes, DataFrame supports dynamic column manipulation, akin to Excel tables. It can read, write, and transform data from formats like CSV or JSON, making it ideal for both analytics and general projects. For a KotlinConf app, DataFrame processed session data from a REST API, allowing developers to filter, sort, and pivot data effortlessly, providing a flexible alternative to rigid data class structures.
Prototyping with Kotlin Notebook
Kotlin Notebook, a plugin for IntelliJ IDEA Ultimate, enhances DataFrame’s prototyping capabilities. Roman demonstrated creating a scratch file to fetch session data via Ktor Client. The notebook’s auto-completion for dependencies, like Ktor or DataFrame, simplifies setup, downloading the latest versions from Maven Central. Interactive tables display hierarchical data, and each code fragment updates variable types, enabling rapid experimentation. This environment suits developers iterating on ideas, offering a low-friction way to test data transformations before production.
Dynamic Type Inference in Action
DataFrame’s compiler plugin, built for the K2 compiler, introduces on-the-fly type inference. Roman showed how it analyzes a DataFrame’s schema during execution, generating extension properties for columns. For example, accessing a title column in a sessions DataFrame feels like using a property, with auto-completion for column names and types. This eliminates manual schema definitions, streamlining data wrangling. Though experimental, the plugin cached schemas efficiently, ensuring performance, as seen when filtering multiplatform talk descriptions.
Handling Hierarchical Data
DataFrame excels with hierarchical structures, unlike flat data classes. Roman illustrated this with nested JSON from the KotlinConf API, converting categories into a DataFrame with grouped columns. Developers can navigate sub-DataFrames within cells, mirroring data class nesting. For instance, a category’s items array became a sub-DataFrame, accessible via intuitive APIs. This capability supports complex data like object subgraphs, enabling developers to transform and analyze nested structures without cumbersome manual mappings.
Building a KotlinConf Schedule
Roman walked through a practical example: creating a daily schedule for KotlinConf. Starting with session data, he converted startsAt strings to LocalDateTime, filtered out service sessions, and joined room IDs with room names from another DataFrame. Sorting by start time and pivoting by room produced a clean schedule, with nulls replaced by empty strings. The resulting HTML table, generated directly in the notebook, showcased DataFrame’s ability to transform REST API data into user-friendly outputs, all with concise, readable code.
Visualizing Data with Kandy
DataFrame integrates with Kandy, JetBrains’ visualization library, to create charts. Roman demonstrated analyzing GitHub commits from the Kotlin repository, grouping them by week to plot commit counts and average message lengths. The resulting chart revealed trends, like steady growth potentially tied to CI improvements. Kandy’s simple API, paired with DataFrame’s data manipulation, makes visualization accessible. Roman encouraged exploring Kandy’s website for examples, highlighting its role in turning raw data into actionable insights.
DataFrame in Production
Moving DataFrame to production is straightforward. Roman showed copying notebook code into IntelliJ’s EAP version, importing the generated schema to access columns as properties. The compiler plugin evolves schemas dynamically, supporting operations like adding a room column and using it immediately. This approach minimizes boilerplate, as seen when serializing a schedule to JSON. Though the plugin is experimental, its integration with K2 ensures reliability, making DataFrame a practical choice for building scalable backend systems, from APIs to data pipelines.
Links:
[DevoxxFR2025] Winamax’s Journey Towards Cross-Platform
In today’s multi-device world, providing a consistent and high-quality user experience across various platforms is a significant challenge for software companies. For online gaming and betting platforms like Winamax, reaching users on desktop, web, and mobile devices is paramount. Anthony Maffert and Florian Yger from Winamax shared their insightful experience report detailing the company’s ambitious journey to unify their frontend applications onto a single cross-platform engine. Their presentation explored the technical challenges, the architectural decisions, and the concrete lessons learned during this migration, showcasing how they leveraged modern web technologies like JavaScript, React, and WebGL to achieve a unified codebase for their desktop and mobile applications.
The Challenge of a Fragmented Frontend
Winamax initially faced a fragmented frontend landscape, with separate native applications for desktop (Windows, macOS) and mobile (iOS, Android), alongside their web platform. Maintaining and developing features across these disparate codebases was inefficient, leading to duplicated efforts, inconsistencies in user experience, and slower delivery of new features. The technical debt associated with supporting multiple platforms became a significant hurdle. Anthony and Florian highlighted the clear business and technical need to consolidate their frontend development onto a single platform that could target all the required devices while maintaining performance and a rich user experience, especially crucial for a real-time application like online poker.
Choosing a Cross-Platform Engine
After evaluating various options, Winamax made the strategic decision to adopt a cross-platform approach based on web technologies. They chose to leverage JavaScript, specifically within the React framework, for building their user interfaces. For rendering the complex and dynamic visuals required for a poker client, they opted for WebGL, a web standard for rendering 2D and 3D graphics within a browser, which can also be utilized in cross-platform frameworks. Their previous experience with JavaScript on their web platform played a role in this decision. The core idea was to build a single application logic and UI layer using these web technologies and then deploy it across desktop and mobile using wrapper technologies (like Electron for desktop and potentially variations for mobile, although the primary focus of this talk seemed to be the desktop migration).
The Migration Process and Lessons Learned
Anthony and Florian shared their experience with the migration process, which was a phased approach given the complexity of a live gaming platform. They discussed the technical challenges encountered, such as integrating native device functionalities (like file system access for desktop) within the web technology stack, optimizing WebGL rendering performance for different hardware, and ensuring a smooth transition for existing users. They touched upon the architectural changes required to support a unified codebase, potentially involving a clear separation between the cross-platform UI logic and any platform-specific native modules or integrations. Key lessons learned included the importance of careful planning, thorough testing on all target platforms, investing in performance optimization, and managing the technical debt during the transition. They also highlighted the benefits reaped from this migration, including faster feature development, reduced maintenance overhead, improved consistency across platforms, and the ability to leverage a larger pool of web developers. The presentation offered a valuable case study for other organizations considering a similar move towards cross-platform development using web technologies.
Links:
- Anthony Maffert: https://www.linkedin.com/in/anthonymaffert/
- Florian Yger: https://www.linkedin.com/in/florianyger/
- Winamax: https://www.winamax.fr/
- Devoxx France LinkedIn: https://www.linkedin.com/company/devoxx-france/
- Devoxx France Bluesky: https://bsky.app/profile/devoxx.fr
- Devoxx France Website: https://www.devoxx.fr/
[KCDUK2024] The Operator Antipattern | Gerald Schmidt
At KCDUK2024, Gerald Schmidt, data platform engineering lead at DS Smith, delivered a candid reflection on the Kubernetes operator pattern, questioning its efficacy in modern platform engineering. Drawing from his experience at Babylon Health, Go City, and Thoughtworks, Gerald shared a journey from enthusiasm to disillusionment, highlighting how operators, despite their promise, often introduce complexity and fragility that outweigh their benefits.
The Allure and Pitfalls of Operators
Gerald opened with his initial excitement for operators, which promised to extend Kubernetes’ API for managing complex stateful applications. He referenced Brandon Phillips’ vision of operators embedding domain expertise to automate tasks, such as managing databases or message queues. However, Gerald’s experience revealed that operators rarely delivered on this promise. Instead, they introduced tight coupling between custom resource definitions (CRDs) and controllers, creating operational challenges.
A pivotal anecdote from his time at a health startup illustrated this. Gerald’s team built operators for data flows, only to face disaster when CRDs were inadvertently deleted, requiring a weekend-long recovery. This incident led to their team losing deployment privileges, underscoring the risks of operators in environments with shrinking teams and heightened scrutiny. Gerald argued that operators, while powerful, often fail to match the robustness of managed services like AWS RDS, which offer superior durability and availability.
Persistent Volumes Over Stateful Applications
Gerald challenged the notion that Kubernetes struggles with stateful applications, suggesting the real issue lies with persistent volumes. Solutions like Thanos and WarpStream, which leverage object storage, address this effectively without relying on operators. He highlighted the maturity of the object storage ecosystem, with providers like AWS S3, Google Cloud Storage, and Wasabi offering cost-effective, reliable alternatives. The Container Object Storage Interface (COSI), though still emerging, promises further simplification, reducing the need for complex operator-based solutions.
He contrasted this with the operator pattern’s limitations, particularly around CRDs. Unlike controllers, which integrate seamlessly with Kubernetes’ control loop, CRDs require administrative privileges and complicate versioning and upgrades. Gerald cited the AWS Controllers for Kubernetes (ACK), still in v1alpha1, as an example of versioning challenges, where upgrades introduce new failure modes and complexity.
Toward Simpler, Developer-Friendly Solutions
Reflecting on developer experience, Gerald advocated for alternatives like config maps over CRDs. He praised Grafana’s approach, which uses config maps for dashboards, avoiding the need for administrative access and simplifying deployment. Similarly, older Prometheus setups allowed developers to control scraping with simple annotations, granting autonomy without the overhead of CRDs. Gerald argued that controllers alone, paired with config maps, provide most of the operator’s benefits without the downsides.
He concluded with a decision framework: only pursue the operator pattern if the use case justifies a domain-specific language. For operational tasks with low blast radius, like Kyverno’s policy enforcement, operators excel. However, for development teams, Gerald recommended avoiding custom operators, as they often lead to wasted effort and fragility, as seen in his team’s abandoned six-month project.
Links:
[KotlinConf2025] Two Years with Kotlin Multiplatform: From Zero to 55% Shared Code
The journey to unified mobile applications is a complex one, fraught with technical and organizational challenges. Rodrigo Sicarelli, a staff software engineer at StoneCo, a leading Latin American fintech company, shared a compelling real-world account of his company’s two-year transition to Kotlin Multiplatform (KMP). This exploration revealed the strategic decisions, hurdles, and impressive achievements that led to a remarkable 55% code sharing across two large-scale mobile applications.
The initial challenge for StoneCo was to evaluate various cross-platform frameworks to find one that could balance the efficiency of code sharing with the critical need for a seamless user experience in the financial sector. Rodrigo detailed the exhaustive process of assessment and the ultimate decision to adopt KMP, a choice that promised to unify their mobile development efforts. A key part of the journey was the organizational shift, which involved training 130 mobile engineers to embrace a new paradigm. Rodrigo emphasized that this was not merely a technical migration but a cultural and educational one, fostering a collaborative spirit and promoting knowledge sharing across teams.
As the adoption matured, the teams faced a number of technical hurdles. One of the primary challenges was ensuring consistent data models and a unified network layer. Rodrigo outlined how they tackled this by consolidating data sources and creating a shared codebase for networking logic, which streamlined development and reduced errors. Another significant obstacle was the integration of KMP into their iOS CI/CD pipeline. He provided a clear explanation of how they overcame this by creating custom Gradle tasks and optimizing their build process, which dramatically improved build times. He also touched upon the importance of addressing the specific needs of iOS developers, particularly concerning the generation of idiomatic Swift APIs from the shared Kotlin code.
A major win for the team was the development of a custom Gradle plugin to manage Kotlin Multiplatform dependencies. This innovation was designed to solve a problem with exposing external libraries to Swift, where the linker would sometimes struggle with duplicate symbols. By adding annotations, the team was able to improve the linking process and reduce build times. This solution not only streamlined their internal workflow but is also planned for open-sourcing, showcasing StoneCo’s commitment to giving back to the community.
Rodrigo concluded by looking to the future, outlining a vision for a single, unified application repository that is user-segment-aware and built with Compose Multiplatform. This forward-looking approach demonstrates a long-term commitment to KMP and a desire to continue pushing the boundaries of shared code. His talk provided invaluable, actionable insights for any organization considering or already in the process of scaling Kotlin Multiplatform.
Links:
- StoneCo website
- Two Years with Kotlin Multiplatform: From Zero to 55% Shared Code | Rodrigo Sicarelli
How to Install an Old Version of Docker on a Recent Debian: A Case Study with Docker 20.10.9 on Debian 13 (Trixie)
In the rapidly evolving landscape of containerization technology, Docker remains a cornerstone for developers and system administrators. However, specific use cases—such as legacy application compatibility, testing, or reproducing historical environments—may necessitate installing an older version of Docker on a modern operating system. This guide provides a detailed walkthrough for installing Docker Engine 20.10.9, a release from September 2021, on Debian 13 (codename “Trixie”), the testing branch of Debian as of September 2025. While the steps can be adapted for other versions or Debian releases, this case study addresses the unique challenges of downgrading Docker on a contemporary distribution.
Introduction: The Challenges and Rationale for Installing an Older Docker Version
Installing an outdated Docker version like 20.10.9 on a recent Debian release such as Trixie is fraught with challenges due to Docker’s evolution and Debian’s forward-looking package management. Docker transitioned from Calendar Versioning (CalVer, e.g., 20.10) to Semantic Versioning (SemVer, starting with 23.0 in May 2023), introducing significant updates in security, features, and dependencies. This creates several obstacles:
- Package Availability and Compatibility: Docker’s official APT repository prioritizes current versions (e.g., 28.x in 2025) for supported Debian releases. Older versions like 20.10.9 are often archived and unavailable via
aptfor newer codenames like Trixie, requiring manual downloads of.debpackages from a compatible release (e.g., bullseye for Debian 11). This can lead to dependency mismatches or installation failures. - Security and Support Risks: Version 20.10.9 is end-of-life (EOL) since mid-2023, lacking official security patches for known vulnerabilities (e.g., CVEs in networking or containerd). This poses risks for production environments. Additionally, compatibility issues may arise with modern WSL2 networking in Windows Subsystem for Linux (WSL) environments.
- Dependency Conflicts: Older Docker versions rely on specific versions of components like
containerd.io, which may conflict with newer libraries on Debian 13, potentially causing installation or runtime errors. - Docker Compose Compatibility: Modern Docker integrates Compose as a plugin (
docker compose), but older setups require the standalonedocker-compose(v1, with hyphen), necessitating a separate binary installation.
Why pursue this downgrade? Legacy applications, specific toolchains, or compatibility with older Dockerfiles may require it—such as maintaining a telemetry stack with Elasticsearch, Kibana, and APM Server in a controlled environment. However, for production or security-sensitive deployments, upgrading to the latest Docker version (e.g., 28.3.3) is strongly recommended. This guide assumes a WSL/Debian Trixie setup but is applicable to native Debian installations, with precautions for data loss and system stability.
Prerequisites
Before proceeding, ensure the following:
- A running Debian 13 (Trixie) system (verify with
lsb_release -cs). - Administrative access (sudo privileges).
- Backup of critical Docker data (e.g., export volumes using
docker volume ls). - Internet access for downloading packages.
- Awareness of risks: Manual package installation bypasses APT’s dependency resolution, and EOL versions lack security updates.
Step 1: Prune All Local Docker Resources
Why This Step is Needed
Before uninstalling the current Docker version (e.g., 28.3.3), pruning all local resources—images, containers, volumes, and networks—ensures a clean slate. This prevents conflicts from residual data, reclaims disk space, and prepares the system for the downgrade. Since pruning is irreversible, backing up critical data (e.g., telemetry stack volumes) is essential.
What It Does
The docker system prune command removes all unused Docker artifacts, including stopped containers, unused images, volumes, and networks, ensuring no remnants interfere with the new installation.
Commands
# Stop all running containers (if any)
docker stop $(docker ps -q) 2>/dev/null || true
# Prune everything: images, containers, volumes, networks, and build cache
docker system prune -a --volumes -f
Verification
Run these commands to confirm cleanup:
docker images -a # Should list no images
docker volume ls # Should be empty
docker network ls # Should show only defaults (bridge, host, none)
docker ps -a # Should show no containers
If permission errors occur, verify your user is in the docker group (sudo usermod -aG docker $USER and log out/in) or use sudo.
Step 2: Remove the Current Docker Installation
Why This Step is Needed
Removing the existing Docker version (e.g., 28.3.3) eliminates potential conflicts in packages, configurations, or runtime components. Residual files or newer dependencies could cause the older 20.10.9 installation to fail or behave unpredictably.
What It Does
This step stops Docker services, purges installed packages, deletes data directories and configurations, and removes the Docker APT repository to prevent accidental upgrades to newer versions.
Commands
# Stop Docker services
sudo systemctl stop docker
sudo systemctl stop docker.socket
# Uninstall Docker packages
sudo apt-get purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo apt-get autoremove -y --purge
# Remove Docker data and configs
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
sudo rm -rf /etc/docker
sudo rm -f /etc/apparmor.d/docker
sudo rm -f /var/run/docker.sock
sudo groupdel docker 2>/dev/null || true
# Remove Docker repository
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.gpg
sudo apt-get update
# Verify removal
docker --version # Should show "command not found"
Reboot WSL if needed (in Windows PowerShell: wsl --shutdown).
Step 3: Install Docker Engine 20.10.9 via Manual .deb Packages
Why This Step is Needed
Debian Trixie’s Docker repository does not include 20.10.9, as it is an EOL version from 2021, unsupported since mid-2023. The standard apt installation fails due to version mismatches, so we manually download and install .deb packages from Docker’s archive for Debian 11 (bullseye), which is compatible with Trixie. This approach bypasses repository limitations but requires careful dependency management.
What It Does
The commands download specific .deb files for Docker CE, CLI, and containerd.io, install them using dpkg, resolve dependencies with apt, and lock the version to prevent upgrades. The process also ensures Docker starts correctly and is accessible without root privileges.
Commands
# Install prerequisites
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# Create directory for downloads
mkdir -p ~/docker-install
cd ~/docker-install
# Download .deb packages for 20.10.9 (bullseye, amd64)
curl -O https://download.docker.com/linux/debian/dists/bullseye/pool/stable/amd64/containerd.io_1.4.13-1_amd64.deb
curl -O https://download.docker.com/linux/debian/dists/bullseye/pool/stable/amd64/docker-ce-cli_20.10.9~3-0~debian-bullseye_amd64.deb
curl -O https://download.docker.com/linux/debian/dists/bullseye/pool/stable/amd64/docker-ce_20.10.9~3-0~debian-bullseye_amd64.deb
# Verify file sizes (should be MBs, not bytes)
ls -lh *.deb
# Install .deb packages
sudo dpkg -i containerd.io_1.4.13-1_amd64.deb
sudo dpkg -i docker-ce-cli_20.10.9~3-0~debian-bullseye_amd64.deb
sudo dpkg -i docker-ce_20.10.9~3-0~debian-bullseye_amd64.deb
# Fix any dependency issues
sudo apt-get install -f
# Hold versions to prevent upgrades
sudo apt-mark hold docker-ce docker-ce-cli containerd.io
# Start and enable Docker
sudo systemctl start docker
sudo systemctl enable docker
# Add user to docker group (log out/in after)
sudo usermod -aG docker $USER
# Verify installation
docker --version # Should show "Docker version 20.10.9, build ..."
docker run --rm hello-world # Test pull and run
# Clean up downloaded files
cd /mnt/c/workarea/development-tools/telemetry-poc/etc/docker/telemetry
rm -rf ~/docker-install
Note: If the curl URLs return 404 errors, browse Docker’s bullseye pool to find the exact filenames (e.g., try docker-ce_20.10.10~3-0~debian-bullseye_amd64.deb if 20.10.9 is unavailable). Use containerd.io_1.4.11-1_amd64.deb if 1.4.13 fails.
Step 4: Install Standalone docker-compose (v1.29.2)
Why This Step is Needed
Modern Docker includes Compose as a plugin (docker compose, v2), but legacy setups like 20.10.9 often require the standalone docker-compose (v1, with hyphen) for compatibility with older workflows or scripts. This binary ensures the hyphenated command is available.
What It Does
Downloads the v1.29.2 binary (the last v1 release, compatible with 20.10.9) from GitHub, installs it to /usr/local/bin, and makes it executable.
Commands
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify
docker-compose --version # Should show "docker-compose version 1.29.2, build ..."
Step 5: Post-Installation and Verification
Why This Step is Needed
Post-installation steps ensure Docker and docker-compose function correctly, especially in a WSL environment where networking can be temperamental. Verifying the setup confirms compatibility with your telemetry stack (e.g., Elasticsearch, Kibana, APM Server).
What It Does
Restarts WSL to apply changes, tests Docker and docker-compose, and rebuilds your telemetry stack. It also checks network accessibility from Windows.
Commands
# Restart WSL (in Windows PowerShell)
wsl --shutdown
# Reopen WSL terminal and verify
docker --version # Should show "Docker version 20.10.9, build ..."
docker-compose --version # Should show "docker-compose version 1.29.2, build ..."
docker run --rm hello-world
Troubleshooting
If issues arise, consider these steps:
- Download Failures: Check Docker’s bullseye pool for correct filenames. Use
curl -I <URL>to verify HTTP status (200 OK). - Dependency Errors: Run
sudo apt-get install -fto resolve. - Docker Not Starting: Check
sudo systemctl status dockerorjournalctl -u docker. - WSL Networking: Update WSL (
wsl --update) and restart Docker (sudo service docker restart). - Share Outputs: Provide
ls -lh ~/docker-install/*.deb,dpkg -l | grep docker, or error messages for debugging.
Conclusion
Installing an older version of Docker, such as 20.10.9, on a recent Debian release like Trixie (Debian 13) is a complex but achievable task, requiring careful management of package dependencies and manual installation of archived .deb files. By pruning existing Docker resources, removing the current installation, and installing bullseye-compatible packages, you can successfully downgrade to meet legacy requirements. The addition of the standalone docker-compose ensures compatibility with older workflows..
However, this approach comes with caveats: version 20.10.9 is end-of-life, lacking security updates, and may face compatibility issues with modern tools or WSL2 networking. For production environments, consider using the latest Docker version (e.g., 28.3.3 as of September 2025) to benefit from ongoing support and enhanced features. Always test thoroughly after installation, and maintain backups to mitigate data loss risks. If you encounter issues or need to adapt this process for other versions, consult Docker’s official repository or community forums for additional resources.
[AWSReInforce2025] How AWS designs the cloud to be the most secure for your business (SEC201)
Lecturer
The presentation is delivered by AWS security engineering leaders who architect the foundational controls that underpin the global cloud infrastructure. Their expertise encompasses hardware security modules, hypervisor isolation, formal verification, and organizational separation of duties across planetary-scale systems.
Abstract
The exposition delineates AWS’s security design philosophy, demonstrating how deliberate architectural isolation, formal verification, and cultural reinforcement create a substrate that absorbs undifferentiated security burden. Through examination of Nitro System enclaves, independent control planes, and hardware-rooted attestation, it establishes that security constitutes the primary reliability pillar, enabling customers to prioritize application innovation over infrastructure protection.
Security as Cultural Imperative and Design Principle
Security permeates AWS culture as the paramount priority, manifesting in organizational structure and technical architecture. Every engineering decision undergoes security review; features ship only when security criteria are satisfied. This cultural commitment extends to compensation—security objectives weigh equally with availability and performance in promotion criteria.
The design principle of least privilege applies ubiquitously: services operate with minimal permissions, even internally. When compromise occurs, blast radius is constrained by default. This philosophy contrasts with traditional enterprises where security is bolted on; at AWS, it is the foundation upon which all else is built.
Hardware-Enforced Isolation via Nitro System
The Nitro System exemplifies security through custom silicon. Traditional servers commingle customer workloads with management firmware; Nitro segregates these domains into dedicated cards—compute, storage, networking—each with independent firmware update channels.
Customer VM → Nitro Hypervisor → Nitro Security Module → Physical CPU
↘ Independent Control Plane → Hardware Attestation
The Nitro Security Module (NSM) maintains cryptographic attestation of the entire software stack. Before a host accepts customer instances, NSM verifies firmware integrity against immutable measurements burned into one-time-programmable fuses. Any deviation prevents boot, eliminating persistent rootkits at the hardware layer.
Independent Control and Data Plane Separation
Control plane operations—API calls, console interactions—execute in isolated cells that never touch customer data. A misconfigured S3 bucket policy might grant public access from the data plane perspective, but the control plane maintains an independent audit stream that detects the anomaly within minutes. This separation ensures configuration drift cannot evade detection.
The demonstration illustrates a public bucket created intentionally for testing. Within 180 seconds, Amazon Macie identifies the exposure, GuardDuty generates a finding, and Security Hub triggers an automated remediation workflow via Lambda. The customer perceives no interruption, yet the risk is mitigated proactively.
Formal Verification and Provable Security
AWS employs mathematical proof for critical components. The s2n TLS library undergoes formal verification using SAW (Software Analysis Workbench), proving absence of memory safety errors in encryption pathways. Similarly, the Firecracker microVM—underpinning Lambda and Fargate—uses TLA+ specifications to verify isolation properties under concurrency.
These proofs extend to hardware: the Nitro enclave attestation protocol is verified using ProVerif, ensuring man-in-the-middle attacks are impossible even if the host OS is compromised. This rigor transforms empirical testing into mathematical certainty for security invariants.
Organizational Isolation and Compensating Controls
Beyond technical boundaries, AWS enforces organizational separation. Teams that manage customer data cannot access control plane systems, and vice versa. This dual-key approach prevents insider threats: a malicious storage engineer cannot modify billing logic.
Compensating controls provide defense in depth. Even if a service principal is compromised, VPC endpoints restrict traffic to authorized networks. Immutable infrastructure—AMI baking, Infrastructure as Code—ensures configuration drift triggers automated replacement rather than manual fixes.
Customer Outcomes and Shared Fate
The infrastructure absorbs complexity so customers need not replicate it. Organizations avoid building global DDoS mitigation, hardware security module fleets, or formal verification teams. Instead, they compose higher-order security patterns: cell-based architectures, zero-trust microsegmentation, and automated compliance evidence collection.
This shared fate model extends to innovation velocity. When AWS hardens the substrate—introducing post-quantum cryptography in KMS, or confidential computing in EC2—customers inherit these capabilities instantly across all regions. Security becomes a force multiplier rather than a drag coefficient.
Conclusion: Security as Substratum for Civilization-Scale Computing
AWS designs security not as a feature but as the invariant property of the computing substrate. Through hardware isolation, formal verification, cultural reinforcement, and independent control planes, it creates a platform where compromise is detected and contained before customer impact. This foundation liberates organizations to build transformative applications—genomic sequencing at population scale, real-time fraud detection for billions of transactions—confident that the underlying security posture is mathematically sound and operationally resilient.