Efficient Inter-Service Communication with Feign and Spring Cloud in Multi-Instance Microservices
In a world where systems are becoming increasingly distributed and cloud-native, microservices have emerged as the de facto architecture. But as we scale
microservices horizontally—running multiple instances for each service—one of the biggest challenges becomes inter-service communication.
How do we ensure that our services talk to each other reliably, efficiently, and in a way that’s resilient to failures?
Welcome to the world of Feign and Spring Cloud.
The Challenge: Multi-Instance Microservices
Imagine you have a user-service that needs to talk to an order-service, and your order-service runs 5 instances behind a
service registry like Eureka. Hardcoding URLs? That’s brittle. Manual load balancing? Not scalable.
You need:
- Service discovery to dynamically resolve where to send the request
- Load balancing across instances
- Resilience for timeouts, retries, and fallbacks
- Clean, maintainable code that developers love
The Solution: Feign + Spring Cloud
OpenFeign is a declarative web client. Think of it as a smart HTTP client where you only define interfaces — no more boilerplate REST calls.
When combined with Spring Cloud, Feign becomes a first-class citizen in a dynamic, scalable microservices ecosystem.
✅ Features at a Glance:
- Declarative REST client
- Automatic service discovery (Eureka, Consul)
- Client-side load balancing (Spring Cloud LoadBalancer)
- Integration with Resilience4j for circuit breaking
- Easy integration with Spring Boot config and observability tools
Step-by-Step Setup
1. Add Dependencies
[xml][/xml]
If using Eureka:
[xml][/xml]
2. Enable Feign Clients
In your main Spring Boot application class:
[java]@SpringBootApplication
@EnableFeignClients
public <span>class <span>UserServiceApplication { … }
[/java]
3. Define Your Feign Interface
[java]
@FeignClient(name = "order-service")
public interface OrderClient { @GetMapping("/orders/{id}")
OrderDTO getOrder(@PathVariable("id") Long id); }
[/java]
Spring will automatically:
- Register this as a bean
- Resolve order-service from Eureka
- Load-balance across all its instances
4. Add Resilience with Fallbacks
You can configure a fallback to handle failures gracefully:
[java]
@FeignClient(name = "order-service", fallback = OrderClientFallback.class)
public interface OrderClient {
@GetMapping("/orders/{id}") OrderDTO getOrder(@PathVariable Long id);
}[/java]
The fallback:
[java]
@Component
public class OrderClientFallback implements OrderClient {
@Override public OrderDTO getOrder(Long id) {
return new OrderDTO(id, "Fallback Order", LocalDate.now());
}
}[/java]
⚙️ Configuration Tweaks
Customize Feign timeouts in application.yml:
feign:
client:
config:
default:
connectTimeout:3000
readTimeout:500
[/yml]
Enable retry:
[xml]
feign:
client:
config:
default:
retryer:
maxAttempts: 3
period: 1000
maxPeriod: 2000
[/xml]
What Happens Behind the Scenes?
When user-service calls order-service:
- Spring Cloud uses Eureka to resolve all instances of order-service.
- Spring Cloud LoadBalancer picks an instance using round-robin (or your chosen strategy).
- Feign sends the HTTP request to that instance.
- If it fails, Resilience4j (or your fallback) handles it gracefully.
Observability & Debugging
Use Spring Boot Actuator to expose Feign metrics:
[xml]
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency[/xml]
And tools like Spring Cloud Sleuth + Zipkin for distributed tracing across Feign calls.
Beyond the Basics
To go even further:
- Integrate with Spring Cloud Gateway for API routing and external access.
- Use Spring Cloud Config Server to centralize configuration across environments.
- Secure Feign calls with OAuth2 via Spring Security and OpenID Connect.
✨ Final Thoughts
Using Feign with Spring Cloud transforms service-to-service communication from a tedious, error-prone task into a clean, scalable, and cloud-native solution.
Whether you’re scaling services across zones or deploying in Kubernetes, Feign ensures your services communicate intelligently and resiliently.
Problem: Spring JMS MessageListener Stuck / Not Receiving Messages
Scenario
A Spring Boot application using ActiveMQ with @JmsListener suddenly stops receiving messages after running for a while. No errors in logs, and the queue keeps growing, but the consumers seem idle.
Setup
-
ActiveMQConnectionFactorywas used. -
The queue (
myQueue) was filling up. -
Restarting the app temporarily fixed the issue.
Investigation
-
Checked ActiveMQ Monitoring (Web Console)
-
Messages were enqueued but not dequeued.
-
Consumers were still active, but not processing.
-
-
Thread Dump Analysis
-
Found that listener threads were stuck in a waiting state.
-
The problem only occurred under high load.
-
-
Checked JMS Acknowledgment Mode
-
Default
AUTO_ACKNOWLEDGEwas used. -
Suspected an issue with message acknowledgment.
-
-
Enabled Debug Logging
-
Added:
-
Found repeated logs like:
-
This hinted at connection issues.
-
-
Tested with a Different Message Broker
-
Using Artemis JMS instead of ActiveMQ resolved the issue.
-
Indicated that it was broker-specific.
-
Root Cause
ActiveMQ’s TCP connection was silently dropped, but the JMS client did not detect it.
-
When the connection is lost,
DefaultMessageListenerContainerdoesn’t always recover properly. -
ActiveMQ does not always notify clients of broken connections.
-
No exceptions were thrown because the connection was technically “alive” but non-functional.
Fix
-
Enabled
keepAlivein ActiveMQ connection -
Forced Reconnection with Exception Listener
-
Implemented:
-
This ensured that if a connection was dropped, the listener restarted.
-
-
Switched to
DefaultJmsListenerContainerFactorywithDMLC-
SimpleMessageListenerContainerwas less reliable in handling reconnections. -
New Configuration:
-
Final Outcome
✅ After applying these fixes, the issue never reoccurred.
🚀 The app remained stable even under high load.
Key Takeaways
-
Silent disconnections in ActiveMQ can cause message listeners to hang.
-
Enable
keepAliveandoptimizeAcknowledgefor reliable connections. -
Use
DefaultJmsListenerContainerFactorywithDMLCinstead ofSMLC. -
Implement an
ExceptionListenerto restart the JMS connection if necessary.
How to Bypass Elasticsearch’s 10,000-Result Limit with the Scroll API
Why the 10,000-Result Limit Exists
What Is the Scroll API?
How to Use the Scroll API: Step by Step
Step 1: Start the Scroll
GET /my_index/_search?scroll=1m
{
"size": 1000,
"query": {
"match_all": {}
}
}
Step 2: Fetch More Results
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "c2NhbjsxMDAwO...YOUR_SCROLL_ID_HERE..."
}
Step 3: Clean Up
DELETE /_search/scroll/c2NhbjsxMDAwO...YOUR_SCROLL_ID_HERE...
A Real-World Example
GET /logs/_search?scroll=2m
{
"size": 500,
"query": {
"match": {
"error_message": "timeout"
}
}
}
-
Batch Size: Stick to a `size` like 500–1000. Too large, and you’ll strain memory; too small, and you’ll make too many requests.
-
Timeout Tuning: Set the scroll duration (e.g., `1m`, `5m`) based on how fast your script processes each batch. Too short, and the context expires mid-run.
-
Automation: Use a script to handle the loop. Python’s `elasticsearch` library, for instance, has a handy scroll helper:
from elasticsearch import Elasticsearch
es = Elasticsearch(["http://localhost:9200"])
scroll = es.search(index="logs", scroll="2m", size=500, body={"query": {"match": {"error_message": "timeout"}}})
scroll_id = scroll["_scroll_id"]
while len(scroll["hits"]["hits"]):
print(scroll["hits"]["hits"]) # Process this batch
scroll = es.scroll(scroll_id=scroll_id, scroll="2m")
scroll_id = scroll["_scroll_id"]
es.clear_scroll(scroll_id=scroll_id) # Cleanup
Why Scroll Beats the Alternatives
Conclusion
[DefCon32] The Rise and Fall of Binary Exploitation
Stephen Sims, a veteran cybersecurity expert, navigates the evolving landscape of binary exploitation, a discipline long revered as the pinnacle of hacking challenges. His presentation at DEF CON 32 examines the impact of modern mitigations like Data Execution Prevention (DEP), Address Space Layout Randomization (ASLR), and newer technologies such as Control-flow Enforcement Technology (CET). Stephen explores how these defenses have reshaped the field, while emphasizing that the pursuit of novel exploitation techniques remains vibrant despite increasing complexities.
The Golden Era of Binary Exploitation
Stephen begins by reflecting on the historical significance of binary exploitation, where vulnerabilities in low-level languages like C++ enabled attackers to manipulate system memory. In the early 2000s, exploiting large applications was a hallmark of hacking prowess. However, Stephen notes that memory safety issues have prompted a shift toward safer languages like Rust, though these are not yet mature enough to fully replace C++. This transition has made exploitation more challenging but not obsolete.
Impact of Modern Mitigations
Delving into technical details, Stephen dissects key mitigations like DEP, which prevents code execution in data memory, and ASLR, which randomizes memory addresses. He also discusses CET, which enforces control-flow integrity, and Virtualization-Based Security (VBS), which isolates critical processes. These protections, often disabled by default on Windows to avoid breaking applications, have significantly raised the bar for attackers. Stephen illustrates their enforcement through practical examples, showing how they thwart traditional exploits.
Ethical and Legislative Challenges
Stephen addresses the ethical dilemmas facing researchers, noting that restrictive legislation, such as the Paul Maul Act, could push exploit development underground. He argues that the more researchers are constrained, the greater the risk of unethical markets flourishing. By sharing insights from past research, including contributions from Jeremy Tinder and Haroon Mir, Stephen underscores the need for responsible disclosure to balance innovation with security.
The Future of Exploitation
Concluding, Stephen likens modern exploit development to skateboarding legend Tony Hawk, where past techniques are now accessible to newcomers, enabling rapid advancement. He predicts that as bounties for zero-day exploits rise—some now fetching $500,000—the incentive to bypass mitigations will persist. Stephen encourages researchers to innovate ethically, leveraging open knowledge to uncover new vulnerabilities while navigating an increasingly fortified digital landscape.
Links:
Elastic APM: When to Use @CaptureSpan vs. @CaptureTransaction?
If you’re working with Elastic APM in a Java application, you might wonder when to use `@CaptureSpan` versus `@CaptureTransaction`. Both are powerful tools for observability, but they serve different purposes.
🔹 `@CaptureTransaction`:
Use this at the entry point of a request, typically at a controller, service method, or a background job. It defines the start of a transaction and allows you to trace how a request propagates through your system.
🔹 `@CaptureSpan`:
Use this to track sub-operations within a transaction, such as database queries, HTTP calls, or specific business logic. It helps break down execution time and pinpoint performance bottlenecks inside a transaction.
📌 Best Practices:
✅ Apply @CaptureTransaction at the highest-level method handling a request.
✅ Use @CaptureSpan for key internal operations you want to monitor.
✅ Avoid excessive spans—instrument only critical code paths to reduce overhead.
By balancing these annotations effectively, you can get detailed insights into your app’s performance while keeping APM overhead minimal.
Java’s Emerging Role in AI and Machine Learning: Bridging the Gap to Production
While Python dominates in model training, Java is becoming increasingly vital for deploying and serving AI/ML models in production. Its performance, stability, and enterprise integration capabilities make it a strong contender.
Java Example: Real-time Object Detection with DL4J and OpenCV
[java]
import …
public class ObjectDetection {
public static void main(String[] args) {
String modelPath = "yolov3.weights";
String configPath = "yolov3.cfg";
String imagePath = "image.jpg";
Net net = Dnn.readNet(modelPath, configPath);
Mat image = imread(imagePath);
Mat blob = Dnn.blobFromImage(image, 1 / 255.0, new Size(416, 416), new Scalar(0, 0, 0), true, false);
net.setInput(blob);
MatVector detections = net.forward(); // Inference
// Process detections (bounding boxes, classes, confidence)
// … (complex logic for object detection results)
// Draw bounding boxes on the image
// … (OpenCV drawing functions)
imwrite("detected_objects.jpg", image);
}
}
[/java]
Python Example: Similar Object Detection with OpenCV and YOLO
[python]
import numpy as np
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
image = cv2.imread("image.jpg")
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
detections = net.forward()
# Process detections (bounding boxes, classes, confidence)
# … (simpler logic, NumPy arrays)
# Draw bounding boxes on the image
# … (OpenCV drawing functions)
cv2.imwrite("detected_objects.jpg", image)
[/python]
Comparison and Insights:
- Syntax and Readability: Python’s syntax is generally more concise and readable for data science and AI tasks. Java, while more verbose, offers strong typing and better performance for production deployments.
- Library Ecosystem: Python’s ecosystem (NumPy, OpenCV, TensorFlow, PyTorch) is more mature and developer-friendly for AI/ML development. Java, with libraries like DL4J, is catching up, but its strength lies in enterprise integration and performance.
- Performance: Java’s performance is often superior to Python’s, especially for real-time inference and high-throughput applications.
- Enterprise Integration: Java’s ability to seamlessly integrate with existing enterprise systems (databases, message queues, APIs) is a significant advantage.
- Deployment: Java’s deployment capabilities are more robust, making it suitable for mission-critical AI applications.
Key Takeaways:
- Python is excellent for rapid prototyping and model training.
- Java excels in deploying and serving AI/ML models in production environments, where performance and reliability are paramount.
- The choice between Java and Python depends on the specific use case and requirements.
CTO Perspective: Choosing a Tech Stack for Mainframe Rebuild
Original post
From LinkedIn: https://www.linkedin.com/posts/matthias-patzak_cto-technology-activity-7312449287647375360-ogNg?utm_source=share&utm_medium=member_desktop&rcm=ACoAAAAWqBcBNS5uEX9jPi1JPdGxlnWwMBjXwaw
Summary of the question
As CTO for a mainframe rebuild (core banking/insurance/retail app, 100 teams/1000 people with Cobol expertise), considering Java/Kotlin, TypeScript/Node.js, Go, and Python. Key decision criteria are technical maturity/stability, robust community, and innovation/adoption. The CTO finds these criteria sound and seeks a language recommendation.
TL;DR: my response
- Team, mainframe rebuild: Java/Kotlin are frontrunners due to maturity, ecosystem, and team’s Java-adjacent skills. Go has niche potential. TypeScript/Node.js and Python less ideal for core.
- Focus now: deep PoC comparing Java (Spring Boot) vs. Kotlin on our use cases. Evaluate developer productivity, readability, interoperability, performance.
- Develop comprehensive Java/Kotlin training for our 100 Cobol-experienced teams.
- Strategic adoption plan (Java, Kotlin, or hybrid) based on PoC and team input is next.
- This balances proven stability with modern practices on the JVM for our core.
My detailed opinion
As a CTO with experience in these large-scale transformations, my priority remains a solution that balances technical strength with the pragmatic realities of our team’s current expertise and long-term maintainability.
While Go offers compelling performance characteristics, the specific demands of our core business application – be it in banking, insurance, or retail – often prioritize a mature ecosystem, robust enterprise patterns, and a more gradual transition path for our significant team. Given our 100 teams deeply skilled in Cobol, the learning curve and the availability of readily transferable concepts become key considerations.
Therefore, while acknowledging Go’s strengths in certain cloud-native scenarios, I want to emphasize the strategic advantages of the Java/Kotlin ecosystem for our primary language choice, with a deliberate hesitation and deeper exploration between these two JVM-based options.
Re-emphasizing Java and Exploring Kotlin More Deeply:
-
Java’s Enduring Strength: Java’s decades of proven stability in building mission-critical enterprise systems cannot be overstated. The JVM’s resilience, the vast array of mature libraries and frameworks (especially Spring Boot), and the well-established architectural patterns provide a solid and predictable foundation. Moreover, the sheer size of the Java developer community ensures a deep pool of talent and readily available support for our teams as they transition. For a core system in a regulated industry, this level of established maturity significantly mitigates risk.
-
Kotlin’s Modern Edge and Interoperability: Kotlin presents a compelling evolution on the JVM. Its modern syntax, null safety features, and concise code can lead to increased developer productivity and reduced boilerplate – benefits I’ve witnessed firsthand in JVM-based projects. Crucially, Kotlin’s seamless interoperability with Java is a major strategic advantage. It allows us to:
- Gradually adopt Kotlin: Teams can start by integrating Kotlin into existing Java codebases, allowing for a phased learning process without a complete overhaul.
- Leverage the entire Java ecosystem: Kotlin developers can effortlessly use any Java library or framework, giving us access to the vast resources of the Java world.
- Attract modern talent: Kotlin’s growing popularity can help us attract developers who are excited about working with a modern, yet stable, language on a proven platform.
Why Hesitate Between Java and Kotlin?
The decision of whether to primarily adopt Java or Kotlin (or a strategic mix) requires careful consideration of our team’s specific needs and the long-term vision:
- Learning Curve: While Kotlin is designed to be approachable for Java developers, there is still a learning curve associated with its new syntax and features. We need to assess how quickly our large Cobol-experienced team can become proficient in Kotlin.
- Team Preference and Buy-in: Understanding our developers’ preferences and ensuring buy-in for the chosen language is crucial for successful adoption.
- Long-Term Ecosystem Evolution: While both Java and Kotlin have strong futures on the JVM, we need to consider the long-term trends and the level of investment in each language within the enterprise space.
- Specific Use Cases: Certain parts of our system might benefit more from Kotlin’s conciseness or specific features, while other more established components might initially remain in Java.
Proposed Next Steps (Revised Focus):
- Targeted Proof of Concept (PoC) – Deep Dive into Java and Kotlin: Instead of a broad PoC including Go, let’s focus our initial efforts on a detailed comparison of Java (using Spring Boot) and Kotlin on representative use cases from our core business application. This PoC should specifically evaluate:
- Developer Productivity: How quickly can teams with a Java-adjacent mindset (after initial training) develop and maintain code in both languages?
- Code Readability and Maintainability: How do the resulting codebases compare in terms of clarity and ease of understanding for a large team?
- Interoperability Scenarios: How seamlessly can Java and Kotlin code coexist and interact within the same project?
- Performance Benchmarking: While the JVM provides a solid base, are there noticeable performance differences for our specific workloads?
- Comprehensive Training and Upskilling Program: We need to develop a detailed training program that caters to our team’s Cobol background and provides clear pathways for learning both Java and Kotlin. This program should include hands-on exercises and mentorship opportunities.
- Strategic Adoption Plan: Based on the PoC results and team feedback, we’ll develop a strategic adoption plan that outlines whether we’ll primarily focus on Java, Kotlin, or a hybrid approach. This plan should consider the long-term maintainability and talent acquisition goals.
While Go remains a valuable technology for specific niches, for the core of our mainframe rebuild, our focus should now be on leveraging the mature and evolving Java/Kotlin ecosystem and strategically determining the optimal path for our large and experienced team. This approach minimizes risk while embracing modern development practices on a proven platform.
[OxidizeConf2024] Safety Compliance of Rust Libraries
Navigating Automotive Safety Standards
The automotive industry’s shift toward software-defined vehicles has intensified the need for robust safety compliance, particularly for software components used in safety-critical applications. At OxidizeConf2024, Amit Dharmapurikar and Gnana Ganesh from Thoughtworks delivered an insightful presentation on qualifying Rust libraries for compliance with ISO 26262, a standard governing functional safety in automotive systems. With Thoughtworks’ expertise in software-defined vehicles, Amit and Gnana provided a comprehensive overview of the processes and tools required to ensure Rust libraries meet stringent safety requirements, focusing on the Rust Core library as a case study.
ISO 26262 mandates rigorous documentation, requirement coverage, and structural code coverage to ensure software reliability in electronic control units (ECUs). Amit emphasized that while the Ferrocene compiler, developed by Ferrous Systems, has already achieved safety compliance, libraries—both standard and third-party—must also be qualified. This involves producing formal specifications, verifying requirements through testing, and generating code coverage reports. The speakers highlighted the collaborative effort with Ferrous Systems to qualify the Rust Core library, underscoring the importance of aligning open-source tools with automotive standards.
Documentation and Requirement Coverage
A cornerstone of ISO 26262 compliance is comprehensive documentation, which serves as a formal specification of software components. Gnana detailed how Thoughtworks approaches this by deriving testable requirements from the Rust Core library’s standard documentation. This process involves translating descriptive text into precise, verifiable requirements, a task that poses challenges due to the library’s frequent updates as an open-source project. To address this, Amit and Gnana proposed developing tools to automate the interpretation of documentation changes, ensuring that requirements remain aligned with the library’s evolution.
Requirement coverage, as mandated by ISO 26262 Part 6, ensures that all functional requirements are tested. The speakers demonstrated a proof-of-concept where requirements for the Rust Core library were linked to test cases, providing traceability essential for audits. This approach leverages open-source tools like Sphinx, which facilitates bidirectional traceability by connecting requirements to code. By integrating these tools into the development pipeline, Thoughtworks ensures that compliance artifacts are generated iteratively, reducing manual effort and enhancing accountability.
Advancing Code Coverage with Rust Tooling
Structural code coverage is another critical aspect of ISO 26262 compliance, requiring developers to measure how thoroughly code is exercised by tests. Amit showcased a demo using the Rust toolchain’s coverage capabilities, specifically the --coverage flag in the test subcommand. This flag, combined with a custom bootstrap command (dotx), embeds profiler builtins into executables, generating profile files that tools like grcov process into coverage reports. The demo illustrated coverage analysis for the Rust Core library, excluding documentation to focus on executable code.
While statement coverage is already supported, Gnana noted that branch coverage is available in draft pull requests, and Modified Condition/Decision Coverage (MCDC) is in progress within the Rust community. These advancements, driven by initiatives like Ferrocene, demonstrate Rust’s growing maturity for safety-critical applications. The speakers acknowledged challenges, such as managing frequent library updates, but emphasized the potential of automated tools to streamline compliance, making Rust a viable choice for automotive software development.
Links:
[DotJs2025] Using AI with JavaScript: Good Idea?
Amid the AI deluge reshaping codecraft, a tantalizing prospect emerges: harnessing neural nets natively in JavaScript, sidestepping Python’s quagmires or API tolls. Wes Bos, a prolific Canadian educator whose Syntax.fm podcast and courses have schooled half a million in JS mastery, probed this frontier at dotJS 2025. Renowned for demystifying ES6 and React, Wes extolled browser-bound inference via Transformers.js, weighing its virtues—privacy’s fortress, latency’s lightning—against hardware’s hurdles, affirming JS’s prowess for sundry smart apps.
Wes’s overture skewered the status quo: cloud fetches or Python purgatory, both anathema to JS purists. His heresy: embed LLMs client-side, ONNX Runtime fueling Hugging Face’s arsenal—sentiment sifters, translation tomes, even Stable Diffusion’s slimmer kin. Transformers.js’s pipeline paradigm gleams: import, instantiate (pipeline('sentiment-analysis')), infer (result = await pipe(input)). Wes demoed a local scribe: prompt yields prose, all sans servers, WebGPU accelerating where GPUs oblige. Onyx.js, his bespoke wrapper, streamlines: model loads, GPU probes, inferences ignite—be it code completion or image captioning.
Trade-offs tempered triumph. Footprints fluctuate: 2MB wisps to 2GB behemoths, browser quotas (Safari’s 2GB cap) constraining colossi. Compute cedes to client: beefy rigs revel, mobiles murmur—Wes likened Roblox’s drain to LLM’s voracity. Yet, upsides dazzle: zero egress fees, data’s domicile (GDPR’s grace), offline oases. 2025’s tide—Chrome’s stable WebNN, Firefox’s flag—heralds ubiquity, Wes forecasting six-month Safari stability. His verdict: JS, with its ubiquity and ecosystem, carves niches where immediacy reigns—chatbots, AR filters—not every oracle, but myriad muses.
Wes’s zeal stemmed personal: from receipt printers to microcontroller React, JS’s whimsy fuels folly. Transformers.js empowers prototypes unbound—anime avatars, code clairvoyants—inviting creators to conjure without concessions.
Client-Side Sorcery Unveiled
Wes unpacked pipelines: sentiment sorters, summarizers—Hugging Face’s trove, ONNX-optimized. Onyx’s facade: await onnx.loadModel('gpt2'), GPU fallback, inferences instantaneous. WebGPU’s dawn (Chrome 2025 stable) unlocks acceleration, privacy paramount—no telemetry trails.
Balancing Bytes and Burdens
Models’ mass mandates moderation: slim variants suffice for mobile, diffusion downsized. Battery’s bite, CPU’s churn—Wes warned of Roblox parallels—yet offline allure and cost calculus compel. JS’s sinew: ecosystem’s expanse, browser’s bastion, birthing bespoke brains.
Links:
[AWSReInventPartnerSessions2024] Institutionalizing Developer-First DevSecOps at Scale: The Intercontinental Exchange Transformation
Lecturer
Clinton Herget serves as Field CTO at Snyk, championing security integration within developer workflows. Craig Lambert is Senior Director of Application Security and Red Team at Intercontinental Exchange (ICE), overseeing security for 1,600 applications supporting 4,000 developers.
Abstract
This examination contrasts traditional and modern software paradigms, detailing ICE’s cultural and technical DevSecOps transformation using Snyk. It explores incentive realignment, risk score consolidation, business-contextualized inventory, and future declarative security models. The shift from post-build audits to continuous integration demonstrates velocity-security equilibrium.
Software Risk Evolution
Legacy: waterfall, silos, monoliths, minimal supply chains. Modern: continuous deployment, platform teams, microservices, opaque dependencies.
DevSecOps integrates security continuously, but legacy tools—separate scans, PDF reports, understaffed security—persist.
ICE Transformation Strategy
Developer Empowerment: IDE/CI/CD real-time feedback via Snyk. Incentives: Gamification, champions, product owner accountability.
Risk Consolidation: Unified SAST, DAST, SCA, IaC metrics. Contextualization: Business criticality mapping.
\# Snyk CI/CD integration
security_scan:
stage: test
script:
- snyk auth $SNYK_TOKEN
- snyk test --severity-threshold=high
- snyk container test $IMAGE
allow_failure: false
Gaps: SAST-DAST correlation, declarative threat models, AI workflow orchestration.
Future State
ML-correlated signals enable “security as code”—developers declare tolerances, platforms enforce.
Implications: accelerated innovation, systematic risk reduction, cultural ownership.