# Josué Barros > Senior Software Engineer (full-stack, data and AI) based in Brazil, working remotely with US and Latin American teams. 8+ years shipping production systems for ExxonMobil, Sephora, Indeed, Bradesco, CCR and SulAmérica. Delivers with an AI agent pipeline (spec first, PM → Dev → QA agents, tests gate every merge, token budgets). Open to senior full-time roles. ## Hiring - Open to: senior full-time roles in full-stack, data platform or AI engineering, remote. - Book an intro call: https://calendly.com/goldenglowitsolutions/1-1-with-josue-barros - About page: https://josuebarros.com/about - LinkedIn: https://linkedin.com/in/joshbarros - GitHub: https://github.com/joshbarros - Email: goldenglowitsolutions@gmail.com ## Selected results - 65% faster homepage render on a global e-commerce platform serving millions of users - Dashboard load time cut from 15s to 2s on an enterprise analytics platform (Redis caching) - 30% lower infrastructure cost and deploy time after moving a data platform to Terraform + Azure DevOps - 40% lower mean time to recovery on high-volume insurance systems (Prometheus + Grafana) ## Companies - ExxonMobil (2026 – present): full-stack analytics — React, FastAPI, Snowflake, Redis - ComPsych via Factored (2025 – 2026): embedded analytics — Java, Spring Boot, Angular, Power BI, Azure - Sephora via Stateside (2025): web performance — React, Core Web Vitals - CCR via Triad Integration (2024 – 2025): data engineering — Azure Databricks, Data Factory, AKS, Terraform - SulAmérica via Keyrus (2024): event-driven backends — Java, Go, Kafka, GKE - Xogito Group (2023 – 2024): backend — Java, Spring, PostgreSQL - Alpha Technologies (2022 – 2024): full-stack — React, Next.js, Node.js - Indeed via InAllMedia (2022): backend — Java, GraphQL, gRPC, Redis - Bradesco via NTT Data (2022): banking — Java, Spring, Oracle - Independent (2018 – 2021): full-stack — React, React Native, Go, Node.js, Django ## Skills - AI engineering: AI agents, MCP, RAG, LangGraph, Claude, OpenAI, vector databases - Data: Snowflake, Databricks, PySpark, Power BI, Microsoft Fabric, Airflow - Backend: Python, FastAPI, Java, Kotlin, Spring Boot, C#, .NET, Go, Node.js, Kafka, Redis - Frontend: React, TypeScript, Next.js, Angular, React Native - Cloud: Azure, AWS, GCP, Kubernetes, Terraform, CI/CD, OpenTelemetry ## Projects - [production-rag](https://github.com/joshbarros/production-rag): citation-grounded document QA with evals, MCP endpoint and token budgets - [appsec-incident-lab](https://github.com/joshbarros/appsec-incident-lab): production-style AppSec incident-response and observability lab (Go, Python, Next.js) - [open-game-forge](https://github.com/joshbarros/open-game-forge): reproducible game-asset generation pipeline on ComfyUI + RunPod - [dotnet-ecommerce-app](https://github.com/joshbarros/dotnet-ecommerce-app): ASP.NET Core 10 + PostgreSQL + Angular e-commerce app - [yt-series-terraform-azure](https://github.com/joshbarros/yt-series-terraform-azure): Terraform + Azure YouTube series companion repo ## Blog - [AEO, GEO and SEO for a Developer Site: The Checklist I Actually Applied](https://josuebarros.com/blog/aeo-geo-seo-developer-site-checklist): A practical, evidence-aware checklist for making a developer blog findable by Google and cited by AI assistants: what to change, how to verify it, and what is still unproven. - [Claude Code vs Codex on the Same Ticket: A Measured Test With Hidden Tests](https://josuebarros.com/blog/claude-code-vs-codex-same-ticket-test): I gave Claude Code and Codex the same CSV-export ticket with nine acceptance criteria and eleven hidden tests. Both passed everything. Here are the times, the setup, and what the test cannot tell you. - [llms.txt: What It Is, a Real Example, and an Honest Verdict](https://josuebarros.com/blog/llms-txt-what-it-is-example-and-honest-verdict): What llms.txt is, the exact file I publish on josuebarros.com, how to validate it, and why I treat it as a cheap bet instead of a ranking factor. - [The N+1 Query Problem, Measured: 2,001 Queries vs One JOIN](https://josuebarros.com/blog/n-plus-1-query-problem-measured): What the N+1 query problem is, how to spot it, and what it costs: 2,001 queries took 47.7 ms in-process versus 2.8 ms for one JOIN, with the code and the limits of the test. - [12 Performance Numbers Every Developer Should Measure Once](https://josuebarros.com/blog/performance-numbers-every-developer-should-measure): Twelve small, reproducible measurements across Java, Go, Python, JavaScript, SQL and Linux, with the numbers, the setup and the caveats behind each one. - [Deploy Next.js to Azure App Service with Terraform in 3 Commands](https://josuebarros.com/blog/deploy-nextjs-azure-terraform-3-commands): From zero to a live URL in under 10 minutes. No portal clicking. No manual config. Everything is code — and it costs $13/month. - [GitHub Spec Kit: Why You Should Stop Vibe Coding and Start Specifying](https://josuebarros.com/blog/github-spec-kit-stop-vibe-coding): GitHub's open-source toolkit forces structure on AI-assisted development. Four gated phases — Specify, Plan, Tasks, Implement — that turn chat-driven chaos into repeatable engineering. - [How I Got 350 Views on My First YouTube Video (And What I'd Do Differently)](https://josuebarros.com/blog/how-i-got-350-views-first-youtube-video): Day 4 stats: 350 views, 39 subscribers, 41% from Reddit. The exact promotion strategy, what worked, what failed, and the one mistake that tanked my CTR. - [Harness.io: The $5.5B DevOps Platform Nobody Talks About](https://josuebarros.com/blog/harness-io-devops-platform-honest-look): AI-powered CI/CD, feature flags, cloud cost management, and chaos engineering in one platform. How Harness compares to GitHub Actions and GitLab CI — and when it's worth the price. - [7 Terraform Mistakes Even Senior Engineers Make](https://josuebarros.com/blog/terraform-mistakes-senior-engineers-make): After 8 years of shipping infrastructure at Sephora, Bradesco, and Indeed — these are the mistakes I still see in production Terraform codebases. - [The BMAD Method: Stop Treating AI Like One Developer — Give It a Team](https://josuebarros.com/blog/bmad-method-ai-agents-that-follow-process): Breakthrough Method for Agile AI-Driven Development assigns 12+ specialized agent personas — PM, Architect, Developer, QA — instead of one generalist. Here's how it works and when to use it. - [I Built 28 Free Developer Tools with Next.js — Here's What I Learned](https://josuebarros.com/blog/free-developer-tools-i-built-with-nextjs): JSON Formatter, OG Image Generator, Regex Tester, and 25 more. All free, no signup. What I learned building them and how they drive 560+ SEO pages. - [How I Plan to Record 100+ Cloud Videos for Under $50](https://josuebarros.com/blog/azure-costs-destroy-after-recording): Pay-as-you-go cloud + terraform destroy after every recording session. The cost math behind building a massive YouTube series on a budget. - [Why Every SaaS Founder Should Learn Terraform (Not Just DevOps Engineers)](https://josuebarros.com/blog/why-every-saas-needs-terraform): You don't need to be a DevOps engineer to benefit from infrastructure as code. If you're building a SaaS, Terraform saves you time, money, and 3 AM incidents. ## Benchmarks (measured results, with code and caveats) - [Claude Code vs Codex on the same ticket: both 14/14 hidden tests](https://josuebarros.com/benchmarks/claude-code-vs-codex-same-ticket): On a CSV-export ticket with 9 acceptance criteria, 3 visible and 11 hidden tests, Claude Code finished in 36 s (about $0.20) and Codex in about 50 s; both passed all 14 tests. One run each on one small ticket. - [gzip vs brotli on a 2.72 MB JSON response: 0.34 MB vs 0.25 MB](https://josuebarros.com/benchmarks/gzip-vs-brotli-json-response-size): A 20,000-row JSON response of 2.72 MB compressed to 0.34 MB with gzip -6 (12%), 0.30 MB with brotli q5 and 0.25 MB with brotli q11. - [WebP vs PNG file size: 0.07 MB vs 2.89 MB for the same graphic (JPEG: 0.24 MB)](https://josuebarros.com/benchmarks/png-vs-jpeg-vs-webp-file-size): The same 1792x2240 flat-color graphic was 2.89 MB as PNG, 0.24 MB as JPEG (q85) and 0.07 MB as WebP (q80). - [100,000 goroutines in Go: about 273 MB, 568 ms](https://josuebarros.com/benchmarks/go-100k-goroutines-memory): Holding 100,000 goroutines alive at once used about 273 MB of runtime memory (roughly 2.7 KB each) and the whole run, including releasing them and summing a shared total, finished in 568 ms. - [Go hello world binary size: 2.0 MB, 1.4 MB stripped, 1.2 MB for Linux](https://josuebarros.com/benchmarks/go-hello-world-binary-size): A default go build produced a 2.0 MB binary, -ldflags="-s -w" reduced it to 1.4 MB, and cross-compiling for linux/amd64 with the same flags produced a 1.2 MB statically linked executable. - [Go slice preallocation: 0.95 ms vs 4.49 ms, 1 vs 39 allocations](https://josuebarros.com/benchmarks/go-slice-preallocation): Yes. Appending 1,000,000 ints took 4.49 ms, 41.7 MB and 39 allocations without preallocation, and 0.95 ms, 8.0 MB and 1 allocation with make([]int, 0, N). - [Go strings.Builder vs +=: 0.18 ms vs 163.9 ms, 21 vs 50,097 allocations](https://josuebarros.com/benchmarks/go-strings-builder-vs-plus-concat): Yes. Building a 50,000-character string took 163.9 ms, 1.35 GB of allocations and 50,097 allocs with +=, versus 0.18 ms, 212 KB and 21 allocs with strings.Builder in go test -bench. - [Go sync.Pool vs allocating a new buffer: 21 ns vs 624 ns, 0 allocations](https://josuebarros.com/benchmarks/go-sync-pool-vs-new-buffer): In a micro-benchmark, reusing buffers from sync.Pool took 21 ns/op with 0 allocations, versus 624 ns/op and 4,096 B/op for allocating a fresh buffer each time (about 29x faster). - [Java ArrayList.contains vs HashSet.contains: 1,762 ms vs 0.25 ms](https://josuebarros.com/benchmarks/java-arraylist-vs-hashset-contains): Yes. In a test of 10,000 lookups in a collection of 100,000 integers on JDK 17, ArrayList.contains took 1,762 ms and HashSet.contains took 0.25 ms, because a list scans elements one by one while a hash set jumps straight to the bucket. - [Java parallel streams: 3.6x slower on 1,000 items, 6x faster on 50 million](https://josuebarros.com/benchmarks/java-parallel-streams-small-vs-large): On an 8-core machine with JDK 17, summing 1,000 elements took 0.030 ms sequentially and 0.109 ms in parallel (3.6x slower), 100,000 elements was a tie, and 50 million elements took 65.5 ms sequentially vs 10.6 ms in parallel (6x faster). - [Java records vs a classic data class: 1 line vs 34](https://josuebarros.com/benchmarks/java-records-vs-classic-class): A three-field data holder with constructor, accessors, equals, hashCode and toString took 34 lines as a classic class and 1 line as a record (Java 16+), with identical toString, equals and hashCode behavior in a test run. - [Java streams vs for loops: 4.4 ms vs 4.5 ms (boxing costs 6.5 ms)](https://josuebarros.com/benchmarks/java-streams-vs-for-loop): Not for primitives. Summing the squares of the even numbers in 5 million ints took 4.4 ms with a for loop, 4.5 ms with an IntStream and 6.5 ms with a boxed Stream on JDK 17; boxing, not streams, was the cost. - [Java StringBuilder vs += in a loop: 0.5 ms vs 448 ms](https://josuebarros.com/benchmarks/java-stringbuilder-vs-string-concat-loop): Yes. Appending one character 100,000 times took 448 ms with s += "x" and 0.5 ms with StringBuilder.append on JDK 17 after JIT warm-up, about 900 times faster, because strings are immutable and every += copies the whole string. - [JavaScript Array.includes vs Set.has: 386.6 ms vs 0.56 ms](https://josuebarros.com/benchmarks/javascript-array-includes-vs-set-has): In Node 22, 10,000 lookups in 100,000 items took 386.6 ms with Array.includes and 0.56 ms with Set.has, about 690x faster. - [JavaScript bundle size: moment + lodash 138 KB vs dayjs + lodash-es 11 KB](https://josuebarros.com/benchmarks/javascript-bundle-size-moment-lodash-vs-dayjs): A tiny file that formats a date and chunks an array bundled to 138 KB (47 KB gzipped) with moment and full lodash, and 11 KB (4.9 KB gzipped) with dayjs and lodash-es/chunk, using esbuild --bundle --minify. - [JavaScript Promise.all vs sequential await: 0.10 s vs 1.01 s](https://josuebarros.com/benchmarks/javascript-promise-all-vs-sequential-await): Ten independent 100 ms calls took 1.01 s when awaited one after another and 0.10 s with Promise.all in Node 22. - [cron vs systemd timer: where does the error go?](https://josuebarros.com/benchmarks/cron-vs-systemd-timer-failure-logging): On Ubuntu 24.04, cron recorded only that it started the command; the "disk full" message and exit code 3 were not logged. The systemd timer's journal captured stdout, stderr and the exit status of every run. - [journald disk usage: 47.7 MB to 16.0 MB after rotate and vacuum](https://josuebarros.com/benchmarks/journald-disk-usage-cap): After writing 200,000 log lines, journalctl --disk-usage reported 47.7 MB; journalctl --rotate then --vacuum-size=20M reduced it to 16.0 MB. A permanent cap is SystemMaxUse in a journald.conf drop-in. - [logrotate compress: 24.8 MB to 3.8 MB](https://josuebarros.com/benchmarks/logrotate-compress-log-size): 300,000 synthetic request log lines (24.8 MB) became a 3.8 MB .gz file after logrotate with compress, 85% smaller. - [nginx proxy_cache: 868 vs 70 requests/s, 1 backend hit vs 200](https://josuebarros.com/benchmarks/nginx-proxy-cache-requests-per-second): In front of a backend that takes 200 ms per request, ab -n 200 -c 20 measured 69.8 requests/s with 200 backend hits without a cache and 868.2 requests/s with 1 backend hit using proxy_cache for 30 s. - [systemd MemoryMax: OOM-kill a runaway process without taking down the host](https://josuebarros.com/benchmarks/systemd-memorymax-oom-kill): Running a script that allocated 50 MB per loop with systemd-run -p MemoryMax=300M -p MemorySwapMax=0 got the process OOM-killed at the cap while the host still had about 7 GB available. - [DuckDB vs Polars vs pandas on 30 million rows: 6.6 s vs 22.9 s vs 178 s](https://josuebarros.com/benchmarks/duckdb-vs-polars-vs-pandas-30-million-rows): A group-by on 30 million rows (1.3 GB CSV) took 6.6 s and 187 MB with DuckDB, 22.9 s and 522 MB with Polars, and 178 s and 568 MB with pandas on a MacBook Air. - [pip vs uv install time: 30.1 s vs 3.8 s (0.4 s with warm cache)](https://josuebarros.com/benchmarks/python-pip-vs-uv-install-time): Installing fastapi, uvicorn, pandas, httpx and pydantic into a fresh virtual environment took 30.1 s with pip (no cache), 3.8 s with uv (no cache) and 0.4 s with uv on a warm cache, in one run each. - [Python __slots__: 92 MB vs 188 MB for 1 million objects](https://josuebarros.com/benchmarks/python-slots-memory-usage): One million instances of a three-attribute class used 188 MB with a normal class and 92 MB with __slots__ (measured with tracemalloc). - [Python asyncio vs threads vs sequential: 0.10 s vs 0.5 s vs 10.4 s](https://josuebarros.com/benchmarks/python-asyncio-vs-threads-vs-sequential): For 100 calls that each wait 100 ms (simulated with sleep), sequential code took 10.4 s, a 20-thread pool 0.5 s and asyncio.gather 0.10 s. - [Python generator vs list comprehension memory: under 1 MB vs 204 MB](https://josuebarros.com/benchmarks/python-generator-vs-list-memory): Summing the squares of 5 million integers peaked at 204 MB with a list comprehension and under 1 MB with a generator expression (tracemalloc). - [Python lru_cache: fib(32) in 81 microseconds instead of 0.44 s](https://josuebarros.com/benchmarks/python-lru-cache-fibonacci): fib(32) took 0.44 s with plain recursion and 81 microseconds with @lru_cache(maxsize=None), about 5,400x faster, because each value is computed once. - [N+1 query problem: 2,001 queries (47.7 ms) vs one JOIN (2.8 ms)](https://josuebarros.com/benchmarks/n-plus-1-query-vs-join-sqlite): With 2,000 authors and 20,000 books in in-process SQLite, loading each author's books one query at a time issued 2,001 queries in 47.7 ms; one JOIN took 2.8 ms. Over a network each query adds a round trip, so production is worse. - [Parquet vs CSV: 3x smaller and 3.6x faster in DuckDB](https://josuebarros.com/benchmarks/csv-vs-parquet-duckdb): Converting a 30-million-row CSV (1.35 GB) to Parquet with zstd gave a 0.43 GB file, and the same query dropped from 6.3 s to 1.8 s in DuckDB. The conversion took 25 s. - [SQLite index on 5 million rows: 0.06 ms vs 403 ms per query](https://josuebarros.com/benchmarks/sqlite-index-5-million-rows): In SQLite, a customer_id lookup on 5 million rows took 403 ms per query with a full table scan and 0.06 ms with an index (about 6,400x faster); the index took 3.8 s to build. - [SQLite WAL mode: 0.29 s vs 1.91 s for 3,000 commits](https://josuebarros.com/benchmarks/sqlite-wal-mode-write-speed): 3,000 single-row commits took 1.91 s in the default DELETE journal mode with synchronous=FULL, 0.83 s in WAL with FULL and 0.29 s in WAL with synchronous=NORMAL. - [TypeScript 7 vs 5.9 type-check time: 1.9 s vs 18.8 s](https://josuebarros.com/benchmarks/typescript-7-vs-5-type-check-speed): On a generated project of 400 files (36k lines) in strict mode with noEmit, tsc 5.9.3 took 15.3, 18.8 and 20.8 s across three runs, and tsc 7.0.2 took 1.7, 1.9 and 2.0 s, about 10x faster.