[{"data":1,"prerenderedAt":246},["ShallowReactive",2],{"profile-en":3,"principles-en":27,"projects-en":58,"experience-en":137,"attitudes-en":187,"articles-en-{\"limit\":3}":211},{"brandName":4,"fullName":5,"headline":6,"manifesto":7,"contactIntro":11,"avatar":12,"manifestoImage":13,"social":14},"Danilo Fernando","Danilo Fernando - Senior Software Engineer","Well-built software, reliable integrations, and architecture designed to last.",[8,9,10],"My journey is guided by the belief that code is just a tool to solve complex business problems. With solid experience in the Java and Spring ecosystems, I focus on systems that work AND are easy to maintain and evolve.","Specialised in robust APIs and critical integrations, I believe technical maturity shows up in balanced decisions that weigh innovation against real business needs.","I chase real impact: Clean Code is not aesthetics, it is an economic necessity for long-term product sustainability.","I'm always open to new professional opportunities, technical exchange, or conversations about architecture and software engineering.","\u002Fimages\u002Fprofile\u002Fdanilo.webp","\u002Fimages\u002Fprofile\u002Fdanilo_manifesto.webp",[15,19,23],{"kind":16,"label":17,"href":18},"email","Email","mailto:danilo.bossanova@hotmail.com",{"kind":20,"label":21,"href":22},"linkedin","LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fdanilo-fernando-dev\u002F",{"kind":24,"label":25,"href":26},"github","GitHub","https:\u002F\u002Fgithub.com\u002Fdanilobossanova",[28,33,38,43,48,53],{"id":29,"title":30,"description":31,"icon":32},"clean-architecture","Clean architecture","Decoupled systems that isolate business logic from infrastructure and frameworks.","Layout",{"id":34,"title":35,"description":36,"icon":37},"robust-integrations","Robust integrations","System connections focused on resilience, failure handling, and data consistency.","Network",{"id":39,"title":40,"description":41,"icon":42},"readable-code","Readable code","Code that prioritises human communication and easy reviews.","FileText",{"id":44,"title":45,"description":46,"icon":47},"decisions-with-context","Decisions with context","Choices based on facts, business needs and real constraints.","Brain",{"id":49,"title":50,"description":51,"icon":52},"clear-communication","Clear communication","Translating technical complexity into language every stakeholder understands.","MessageSquare",{"id":54,"title":55,"description":56,"icon":57},"continuous-evolution","Continuous evolution","Constant learning applied to technical and process improvement.","TrendingUp",[59,88,113],{"slug":60,"title":61,"summary":62,"tags":63,"context":67,"solution":68,"result":69,"stack":70,"coverImage":75,"publishedAt":76,"metrics":77,"body":87},"motor-liquidacao-tempo-real","Real-Time Settlement Engine","High-volume financial transaction processing with sub-second latency.",[64,65,66],"Fintech","Scalability","Event-Driven","The existing system could not handle volume peaks, causing queues and reconciliation delays.","Event-driven architecture with Spring Boot, Kafka, and natural-key idempotency.","40% reduction in reconciliation time and 99.9% operational availability under heavy load.",[71,72,73,74],"Java 17","Spring Cloud","Kafka","PostgreSQL","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Ffintech\u002F1200\u002F800","2024-11-03",[78,81,84],{"label":79,"value":80},"Reconciliation","-40%",{"label":82,"value":83},"Availability","99.9%",{"label":85,"value":86},"Throughput","12k tps","## Context\nThe legacy settlement core did not scale horizontally...\n\n## Technical decisions\n- Kafka as the event backbone.\n- Outbox pattern for at-least-once guarantees.\n- Natural-key idempotency on consumers.\n\n## Result\nWithin three months reconciliation time dropped 40% with stable throughput above 12k tps.",{"slug":89,"title":90,"summary":91,"tags":92,"context":95,"solution":96,"result":97,"stack":98,"coverImage":103,"publishedAt":104,"metrics":105,"body":112},"gateway-integracao-multicanal","Multi-Channel Integration Gateway","Marketplace centralisation for unified stock and orders.",[93,94],"E-commerce","Integration","Each marketplace had its own API quirks, causing rework and inventory drift.","Abstraction layer using the Adapter pattern and queue-based orchestration.","Five new partners integrated in under a month, with zero stock sync conflicts.",[99,100,101,102],"Spring Boot","Redis","Docker","JUnit 5","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fecommerce\u002F1200\u002F800","2024-08-12",[106,109],{"label":107,"value":108},"Integrated partners","+5",{"label":110,"value":111},"Time per partner","\u003C1 month","## Context\nOperations depended on one-off scripts per marketplace...\n\n## Solution\nOne adapter per channel, Redis cache and provider contract tests.\n\n## Impact\nFive new marketplaces integrated in under a month, with no stock inconsistency.",{"slug":114,"title":115,"summary":116,"tags":117,"context":120,"solution":121,"result":122,"stack":123,"coverImage":127,"publishedAt":128,"metrics":129,"body":136},"modernizacao-core-bancario","Banking Core Modernisation","Controlled migration from a legacy monolith into microservices.",[118,119],"Legacy Recovery","Clean Arch","Highly coupled legacy monolith with slow deploys and frequent incidents.","Strangler Fig pattern extracting domains progressively with Hexagonal Architecture.","60% faster deploys and a significant drop in technical debt.",[124,99,125,126],"Java","Oracle","Kubernetes","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fbanking\u002F1200\u002F800","2024-03-22",[130,133],{"label":131,"value":132},"Deploy time","-60%",{"label":134,"value":135},"Critical incidents","-45%","## Context\n10+ year old banking core monolith...\n\n## Strategy\nStrangler Fig + Hexagonal to isolate domains.\n\n## Result\n60% faster deploys and a sharp drop in incidents.",[138,150,163,175],{"id":139,"title":140,"items":141},"backend","Backend",[142,145,148],{"name":143,"level":144},"Java (8, 11, 17)","Senior",{"name":146,"level":147},"Spring Boot \u002F Data \u002F Security","Expert",{"name":149,"level":147},"RESTful APIs",{"id":151,"title":152,"items":153},"architecture","Architecture & Quality",[154,157,160],{"name":155,"level":156},"Clean \u002F Hexagonal","Daily",{"name":158,"level":159},"JUnit \u002F Mockito \u002F TDD","Standard",{"name":161,"level":162},"Microservices & Events","Advanced",{"id":164,"title":165,"items":166},"data-infra","Data & Infra",[167,170,172],{"name":168,"level":169},"PostgreSQL \u002F Oracle \u002F MySQL","Proficient",{"name":171,"level":162},"Redis \u002F Caching",{"name":173,"level":174},"Docker \u002F K8s \u002F CI-CD","Practitioner",{"id":176,"title":177,"items":178},"frontend-other","Frontend & Others",[179,182,185],{"name":180,"level":181},"Angular \u002F Vue (TypeScript)","Capable",{"name":183,"level":184},"Cloud (AWS\u002FAzure)","Basics",{"name":186,"level":162},"Kafka \u002F RabbitMQ",[188,192,195,199,203,207],{"id":189,"name":190,"icon":191},"responsibility","Responsibility","ShieldCheck",{"id":193,"name":194,"icon":52},"communication","Communication",{"id":196,"name":197,"icon":198},"collaboration","Collaboration","Users",{"id":200,"name":201,"icon":202},"discipline","Discipline","ClipboardList",{"id":204,"name":205,"icon":206},"analytical","Analytical Thinking","BarChart3",{"id":208,"name":209,"icon":210},"context","Context Awareness","Scale",[212,225,235],{"slug":213,"title":214,"excerpt":215,"category":216,"tags":217,"readTimeMinutes":221,"publishedAt":222,"author":4,"coverImage":223,"body":224},"outbox-pattern-na-pratica","Outbox pattern in practice with Spring Boot","How to guarantee at-least-once delivery without distributed transactions.","Architecture",[218,219,220],"events","spring-boot","kafka",9,"2025-03-01","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Foutbox\u002F1200\u002F600","## The problem\n\nReliably publishing events next to a database transaction is one of the classic\npitfalls in distributed systems. If you write to Postgres and then publish to\nKafka:\n\n```java\n@Transactional\npublic void confirm(Order order) {\n    orderRepository.save(order);       \u002F\u002F ✅ inside DB transaction\n    kafkaTemplate.send(\"orders\", order); \u002F\u002F ❌ outside the transaction\n}\n```\n\nA crash between the two calls is enough for the DB to say *\"confirmed\"* while\nthe rest of the world never hears about it.\n\n## Outbox pattern\n\nThe idea is to write the event in the **same transaction**, in an `outbox`\ntable. A relay reads the table and actually publishes it.\n\n### Minimal schema\n\n```sql\nCREATE TABLE outbox (\n    id           UUID PRIMARY KEY,\n    aggregate    VARCHAR(64)  NOT NULL,\n    event_type   VARCHAR(128) NOT NULL,\n    payload      JSONB        NOT NULL,\n    created_at   TIMESTAMPTZ  NOT NULL DEFAULT now(),\n    published_at TIMESTAMPTZ\n);\nCREATE INDEX outbox_unpublished_idx\n    ON outbox (created_at) WHERE published_at IS NULL;\n```\n\n### Relay\n\nA simple job reads unpublished events, ships them to the broker and marks them\nas published. What matters:\n\n1. **Consumer idempotency** — the relay will republish on failure.\n2. **Lag monitoring** — alert if `outbox` grows faster than it drains.\n3. **Controlled batches** — don't lock the DB pulling 10k rows at a time.\n\n### Gotchas\n\n- Never rely on strict broker ordering; partition by `aggregate_id`.\n- Don't dead-letter into the same table — create `outbox_failed`.\n- Always record the payload schema version.\n\n## When to avoid\n\nIf your system doesn't need at-least-once guarantees, outbox is overkill.\nSpring's `@TransactionalEventListener` covers 80% of cases.",{"slug":226,"title":227,"excerpt":228,"category":216,"tags":229,"readTimeMinutes":231,"publishedAt":232,"author":4,"coverImage":233,"body":234},"custo-real-da-complexidade","The real cost of unnecessary complexity","Why over-engineering is often the fastest path to project failure.",[29,230],"technical-decisions",5,"2025-02-10","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Fcomplexity\u002F1200\u002F600","## Complexity on compound interest\n\nComplexity is the biggest cause of technical bankruptcy I've seen up close.\nEvery \"just in case\" abstraction is an implicit contract with the future —\nand the future always cashes in.\n\n> \"The only thing more expensive than solving the wrong problem is solving\n> the right one with three layers of indirection nobody asked for.\"\n\n### Warning signs\n\n- Abstractions that exist for a single use case.\n- In-house frameworks for problems the ecosystem already solves.\n- \"Let's make it pluggable\" **before** two plugs exist.\n- Dynamic config for something that changes once a year.\n- Mapping layers between identical objects.\n\n### Practical heuristic\n\nBefore creating an abstraction, ask:\n\n1. Are there **two** real consumers today?\n2. Is the cost of extracting later prohibitive?\n3. Does the behaviour actually vary, or just the name?\n\nIf the answer is \"no\" to all three, **inline is the right answer**.\n\n### A concrete example\n\n```java\n\u002F\u002F Before — flexibility nobody asked for\npublic interface UserNotifier {\n    void notify(User user, NotificationPayload payload);\n}\npublic class EmailUserNotifier implements UserNotifier { \u002F* ... *\u002F }\n\n\u002F\u002F After — the system only sends email, period\npublic class EmailService {\n    public void sendWelcome(User user) { \u002F* ... *\u002F }\n}\n```\n\nWhen the second channel appears, you extract the interface in **five minutes**,\ngreen tests and a clear head about what actually changes.\n\n### Summary\n\nStart from real pain, not theoretical elegance. Clean Code is about\n**maintenance cost**, not interfaces per megabyte.",{"slug":236,"title":237,"excerpt":238,"category":99,"tags":239,"readTimeMinutes":242,"publishedAt":243,"author":4,"coverImage":244,"body":245},"testes-integracao-que-nao-mentem","Integration tests that don't lie","TestContainers strategies to keep CI\u002FCD fast without losing confidence in your code.",[240,219,241],"testing","testcontainers",8,"2025-01-18","https:\u002F\u002Fpicsum.photos\u002Fseed\u002Ftests\u002F1200\u002F600","## Green suites, fragile code\n\nA green suite without confidence is worse than no suite — it gives you license\nto ship while the system burns.\n\n### The pattern that works\n\n1. **TestContainers** for real dependencies (Postgres, Kafka, Redis).\n2. **Deterministic fixtures** — no `@Sql` + random.\n3. **One seed per test**, no shared state.\n4. **Assert on data**, not on mock invocation counts.\n\n```java\n@Testcontainers\n@SpringBootTest\nclass OrderConfirmationIT {\n    @Container\n    static PostgreSQLContainer\u003C?> db = new PostgreSQLContainer\u003C>(\"postgres:16\")\n        .withInitScript(\"db\u002Finit.sql\");\n\n    @DynamicPropertySource\n    static void props(DynamicPropertyRegistry reg) {\n        reg.add(\"spring.datasource.url\", db::getJdbcUrl);\n    }\n}\n```\n\n### What that buys\n\n- Tests that **turn green with the code**, not after.\n- Fearless refactors.\n- Objective conversations at code review.",1776457051446]