July 25, 2026
Threat Modeling a FinTech Microservices Application: Where DevSecOps Really Begins
Part 3 of the “Implementing DevSecOps” series

By Lh1l0v3
4 min read
In the first article of this series, I introduced the concept of Shift Left, Verify Right and explained why security should begin long before an application reaches production.
In the second article, I walked through implementing a security architecture for a deliberately vulnerable Python based fintech microservices application using GitHub Actions, Kubernetes, and a collection of security tools.
Before integrating GitLeaks, SonarQube, Trivy, Checkov, OWASP ZAP, or any runtime security controls, there was one activity that shaped every implementation decision.
Threat modeling.
Many discussions about DevSecOps begin with CI/CD pipelines or security scanners. My experience with this project reinforced something different. Security tools are only effective when they are solving problems you have already identified.
Threat modeling provided that understanding.
Why Threat Modeling Comes First
Threat modeling is a structured approach to identifying what needs to be protected, who might attack it, how it could be compromised, and which security controls are most appropriate.
Unlike vulnerability scanning, threat modeling happens during the design phase of the Software Development Life Cycle.
Instead of reacting to vulnerabilities after code has been written, it encourages teams to think about risk before implementation begins.
This is where "Shift Left" actually starts.
The objective is not to predict every possible attack. The objective is to understand the system well enough that security decisions are based on risk rather than assumptions.
Understanding the Application
The project simulated a fintech platform built using Python microservices running on Amazon EKS. The application consisted of several major components:
- Frontend / Backend for Frontend
- Authentication Service
- Transaction Service
- PostgreSQL databases
- GitHub Actions CI/CD pipeline
- Amazon EKS cluster
- Amazon ECR
- HashiCorp Vault
- Falco
- OPA Gatekeeper
- Prometheus, Grafana, and Loki
Each component performed a different function, which meant each component introduced different security risks.
High level architecture of the fintech microservices application.
Identifying Critical Assets
The first step was identifying what actually needed protection. Some assets were obvious:
- Customer credentials
- JWT tokens
- Transaction history
- Account balances
- PostgreSQL databases
Others were less obvious but equally important:
- GitHub repository
- GitHub Actions secrets
- Container images
- Kubernetes manifests
- Terraform configurations
- Vault secrets
- Monitoring infrastructure
- Container registry
Thinking in terms of assets changes your perspective.
Instead of asking how to use a security tool, you begin asking what could happen if an attacker compromises a particular asset.
Mapping Trust Boundaries
Not every component should trust every other component. One of the most important parts of threat modeling was identifying where trust changes.
Examples included:
- Internet to Frontend
- Frontend to Authentication Service
- Authentication Service to PostgreSQL
- Transaction Service to PostgreSQL
- GitHub Actions to AWS
- Amazon ECR to Amazon EKS
- Kubernetes workloads to Vault
Every trust boundary represents an opportunity for an attacker.
Recognizing those boundaries helped determine where authentication, authorization, encryption, policy enforcement, and monitoring were required.
Following the Data
Threat modeling is much easier when you understand how information moves through the application.
For example, a login request and a financial transaction follows different paths.
Data flow illustrating authentication and transaction requests.
Tracing these flows helped identify where sensitive information was created, transmitted, stored, and validated.
Applying STRIDE
Once the architecture and data flows were understood, I applied the STRIDE methodology to each major component. Rather than treating the application as one large system, each component was analyzed individually.
The project documentation included separate threat models for:
- CI/CD Pipeline
- Kubernetes Cluster
- Authentication Service
- Transaction Service
- PostgreSQL Database
- Frontend/BFF
- Observability Stack
- Software Supply Chain
Analyzing components individually made it easier to identify threats that would otherwise be overlooked. Examples included:
Rather than producing a checklist, STRIDE became a way of asking better questions about each component.
From Threats to Security Controls
The most valuable outcome of threat modeling was not the list of threats. It was understanding which controls were needed to reduce those risks. Several implementation decisions came directly from that analysis.
This was one of the biggest lessons from the project.
Security tools did not determine the architecture. The risks identified during threat modeling determined which tools were necessary.
GitHub Actions pipeline executing security controls derived from the threat model.
Maintaining a Risk Register
Another important outcome of the exercise was maintaining a risk register.
Not every threat receives the same priority.
Some risks have a greater likelihood of occurring.
Others would have a greater business impact.
Documenting these risks helped prioritize implementation work instead of treating every issue equally. This also provided a clear record of identified threats, existing mitigations, remaining risks, and recommended actions.
Threat modeling should produce decisions, not just documentation.
Lessons I Learned
This project changed how I think about application security. Initially, I viewed DevSecOps primarily as integrating security tools into a CI/CD pipeline.
Threat modeling showed me that security begins much earlier.
Understanding the architecture, identifying critical assets, defining trust boundaries, and analyzing data flows provided context for every security decision that followed. It also reinforced another important lesson.
Security tools solve technical problems.
Threat modeling identifies which technical problems are worth solving. Without that context, security becomes reactive rather than intentional.
Conclusion
Threat modeling became the foundation for every security control implemented throughout this project.
By identifying risks during the design phase, it became possible to build a pipeline where each security control addressed a specific problem rather than simply adding another scanner. That experience fundamentally changed how I view DevSecOps. Shifting security left is not about running more tools earlier.
It is about understanding risk early enough that every security decision is informed by the architecture, the data, and the threats facing the system.
In the next article, I will take a deeper look at the GitHub Actions security pipeline and explain how tools such as GitLeaks, SonarQube, Trivy, Checkov, OWASP ZAP, Cosign, and policy enforcement work together to automate security throughout the software delivery lifecycle.