zalando

Activity

Stars and mentions · Last 30 days, Oct 7 – Nov 5

GitHub stars13
Mentions9
01234Oct 7Oct 21Nov 5
UTC days · repositories zalando owns2 repositories

Top repositories

zalando’s repositories ranked by pull request authors, as on trending.

Loading

Contributes to

Repositories outside zalando’s account where zalando opened or reviewed pull requests in the past 365 days.

Who noticed zalando

Everyone who starred or forked zalando’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

10posts
Nov 61 post
  1. A response that forgot its attributes 🔍 In Logbook, CachingHttpResponse lost its attributes when withoutBody() was called. My fix keeps them. Merged into @Zalando Logbook 🚀 logbook#2328 #Zalando #Java #BackendDeveloper #OpenSource

    6 views
  2. The Open Source PR I Closed on Purpose (and Why It Was Still Worth It) So far in this series I wrote about PRs that got merged. This post is about one that did not, and why I think it taught me more than some of the merged ones. The issue Riptide is Zalando's HTTP client library for Java. Issue #1859 described a real problem someone had hit in production. Riptide created a separate Failsafe instance for every policy (Retry, Timeout and so on). Failsafe is a library for resilience policies. The problem is that when policies are chained inside one Failsafe instance, Failsafe has built-in protection against deadlocks between combinations like Timeout and Retry. When each policy runs in its own instance, that protection is bypassed. The reporter included a thread dump from their service. Two threads were each waiting for a lock the other one held, and the shared thread pool got blocked. A resilience feature ended up hurting the service. The expected fix: compose all policies into one chain in one Failsafe instance, like this: // One Failsafe instance with both policies chained together, // so Failsafe's own deadlock protection applies. Failsafe.with(timeout, retryPolicy) .getStageAsync(context -> fetchData()); What I did I read the Riptide code, the Failsafe source and the thread dump, worked out how the policies should be composed, and opened PR #1871 with my analysis. What happened The maintainer replied that the Zalando team already had a fix in progress. While building it, they had found a few related changes needed in the framework itself, and they were validating them, especially around Spring Boot starter compatibility. They asked me not to run two parallel fixes for the same issue, and said they would open their PR once validation was done. My honest first reaction: a little disappointed. I had put real time into it. My second thought was clearer: the maintainers are right. Two PRs for the same bug only create extra work for the reviewers. So I closed mine. I also left a note offering to look at their PR when it was up, and shared the order I had used for the policies. Later the maintainer opened #1872, explained why the Timeout sits on the outside (so that retries do not reset it and the whole execution is time-boxed), and thanked me for the analysis. I closed my PR in favor of theirs. Another maintainer also wrote that Riptide is open to contributions from the community. What I learned 1. Ask if someone is already working on it. A comment like "is anyone on this?" before writing code would have saved us both time. I do this first now. 2. A closed PR is not wasted work. I now understand how Failsafe composes policies and where its deadlock guards live. That knowledge stays with me. 3. Learn the reason behind a design, not only the code. The maintainer's explanation of why Timeout wraps everything was something I could not have worked out from the code alone. 4. Close it gracefully. The conversation ended friendly, and I left with a better relationship with the maintainers than I had before. Proof of my work Everything here is public, so you can check it yourself: - zalando/riptide issue #1859, my PR #1871 and the maintainers' PR #1872 - PicnicSupermarket/error-prone-support #2275: extended RequireNonNullExpression rule (merged) - Adyen/adyen-java-api-library #1952: regex fix, shipped in SDK v42.0.0 (merged) - zalando/logbook #2301, #2326, #2327 and #2328: Logbook fixes and features (merged) - Sionna Visualizer: my side project, a 6G + AI dashboard (live demo) - My GitHub: all my repos and contributions Next post: how I choose which issue to work on, so I waste less time than I did with this one. If you are a maintainer, a recruiter or a team looking for someone who learns in public and handles good and bad outcomes the same way, my DMs are open. Tell me in the comments about a PR of yours that did not go through.

  3. Invalid JSON inside a JSON log 🔍 Logbook’s JSON formatter put non-JSON bodies into logs unquoted, making the output invalid JSON. My fix stops it. Merged into @Zalando Logbook 🚀 logbook#2326 #Zalando #Java #BackendDeveloper #OpenSource

    1 like · 58 views
  4. A Tiny Regex Bug in Adyen's Java Library, and How My Fix Shipped in SDK v42.0.0 In my last posts I wrote about why I started open source and about my first merged PR in Zalando Logbook. This one is about a PR in the Adyen Java API Library, and it is a good example of how a very small bug can hide in plain sight. What is the Adyen Java library? Adyen is a global payments company, and this library is how Java applications talk to Adyen's APIs. The whole SDK has to build the correct base URL for every service, for both test and live environments. If that URL is wrong, the payment call goes to the wrong place. The bug The method createBaseURL in Service.java swaps test URLs for live URLs. It used String.replaceFirst() to do that. Here is the catch: replaceFirst() takes a regex, not a plain string. In regex, a dot . means "any character". So a URL part like pal-test.adyen.com was not matching a literal dot. It was matching any character in that position. Simplified, it looked like this: // Before: the dots are treated as "any character" because this is a regex url = url.replaceFirst("pal-test.adyen.com", "pal-live.adyen.com"); For normal URLs it worked fine, which is exactly why nobody noticed. But a URL that only looks similar, with other characters where the dots should be, could still be transformed by mistake. The fix The fix was small. I replaced the affected replaceFirst() calls with String.replace(), which matches plain text with no regex at all: // After: plain literal matching, no regex wildcard risk url = url.replace("pal-test.adyen.com", "pal-live.adyen.com"); I updated the pal-, checkout- and device-api- blocks. I left the two calls without dots (-live to -test and back) as replaceFirst() on purpose, because they were not affected by this issue. I also added a test, testLivePalUrlOnlyMatchesLiteralDots(), using a URL shaped like pal-testXadyenYcom. It looks like the real endpoint but has no literal dots, so it must not be transformed. The test proves the fix and protects against the bug coming back. What the review taught me - Keep the scope tight. The maintainer said he thought about asking me to use .replace in the other places in the method for consistency. Then he decided it was not necessary, because it was unclear whether that would cause some other issue. A good reviewer is careful about changes that were not asked for. It reminded me to fix the bug I was given, not everything I could. - Formatting is part of the PR. The project had recently enforced code formatting, and my PR was blocked until I ran mvn spotless:apply. A tiny thing, but it taught me to run the project's formatter and checks before pushing, every time. - Tests are the real proof. My first version of the test was not strong enough, and I improved it so the URL structurally matched the real one with non-dot separators. A test should fail without your fix, otherwise it proves nothing. The PR was approved and merged, and the change shipped in SDK v42.0.0. Seeing something I wrote inside a release of a payments SDK was a good feeling. The change was small, but real people who use the library get it. What I would tell someone starting out 1. Small bugs are good first PRs. You do not need a big feature to make a real contribution. 2. Read the project's contributing rules and run its formatter and tests before you push. 3. Write a test that fails without your fix. 4. Do not widen the scope. Fix what the issue asks for. Proof of my work Everything here is public, so you can check it yourself: - Adyen/adyen-java-api-library #1952: the regex fix (merged, shipped in v42.0.0) - The original issue #1838 - zalando/logbook #2301: StatusCodeBasedSink and LevelBasedHttpLogWriter (merged) - PicnicSupermarket/error-prone-support #2275: merged after review - Sionna Visualizer: my side project, a 6G + AI dashboard (live demo) - My GitHub: all my repos and contributions Next post: my PR in Picnic's error-prone-support, and what working with a strict reviewer taught me. If you are a maintainer, a recruiter or a team looking for someone who learns in public and likes to collaborate, my DMs are open. Tell me in the comments if you have hit a regex surprise like this one.

  5. My First Merged PR in Zalando Logbook: What I Built and What the Review Taught Me In my last post I wrote about why I started open source. This post is about the first PR that got merged for me in a big project: Zalando Logbook. What is Logbook? Logbook is a Java library from Zalando that logs HTTP requests and responses. If you work with REST APIs, you know why this matters. When something breaks in production, the first thing you want to see is what request came in and what response went out. What I worked on My PR added two things to Logbook: - StatusCodeBasedSink: a sink that makes decisions based on the HTTP status code of the response. - LevelBasedHttpLogWriter: a log writer that uses the status code to pick the log level. The simple idea behind both: a 200 response and a 500 response should not be treated the same. Errors should stand out, and normal traffic should not fill your logs with noise. It got merged in May 2026. You can see the full PR, the code and the review here: zalando/logbook #2301 How I approached it I did not start by writing code. I started by talking to the maintainers on the issue, so I knew what they wanted before I built anything. Then I kept the change small and focused, wrote tests, and signed my commits. Looking back, that order saved me a lot of pain. Writing code first and asking later is how PRs get stuck. What the review taught me Maintainers read very carefully. They do not only check if your code works. They ask: - Does this fit the style of the project? - Will this break anyone who is already using the library? - Is the naming clear for someone who has never seen this code? Answering those questions made my code better than my first version. Reviews are slow sometimes, but they are free teaching from people who know the codebase far better than I do. The part I did not expect After my PR was merged, another contributor found a gap in my own work. The ECS sink did not follow the same status code behavior, so he opened an issue and then a PR to fix it. My first feeling was a little embarrassing. But then I thought about it properly: this is exactly how open source works. Nobody ships perfect code. So instead of rushing to send a competing PR, I reviewed his one and left comments on the threshold behavior and on the docs checklist. You can read that discussion here: zalando/logbook #2379 That was a good lesson for me: reviewing someone else's PR is also a contribution, and it teaches you how others think. What I would tell someone starting out 1. Read the issue and talk to the maintainer first. 2. Keep your PR small. A small diff gets reviewed faster. 3. Take every review comment seriously, even when it feels strict. 4. If someone finds a gap in your work later, treat it as part of the process, not as a failure. What is next In the next post I will write about my PR in the Adyen Java API Library, which shipped in SDK v42.0.0, and how it felt to see my change in a real release. Proof of my work Everything I write about here is public, so you can check it yourself: - zalando/logbook #2301: StatusCodeBasedSink and LevelBasedHttpLogWriter (merged) - adyen/adyen-java-api-library #1952: shipped in SDK v42.0.0 (merged) - PicnicSupermarket/error-prone-support #2275: merged after review - Sionna Visualizer: my side project, a 6G + AI dashboard (live demo) - My GitHub: all my repos and contributions If you are a maintainer, a recruiter or a team looking for someone who learns in public and likes to collaborate, my DMs are open. Tell me in the comments if you work with Logbook or want to contribute to it, I am happy to share what I learned.

  6. One log level for every HTTP response? Too noisy 🔍 Logbook logged every response at one level. My PR sets it by status: 2xx → TRACE, 4xx → WARN, 5xx → ERROR. Merged into @Zalando Logbook 🚀 logbook#2301 #Zalando #Java #BackendDeveloper #OpenSource

    3 views
  7. Colored HTTP logs in the console 🎨 Logbook’s pretty-printed JSON was plain text. My PR adds ANSI colors for local dev, so it’s easier to read. PR open at @ZalandoTech , in discussion 💬 logbook#2385 #Zalando #Java #BackendDeveloper #OpenSource

    5 views
  8. A nice set of guidelines for developing Restful APIs. Provided by Zalando. zalando/restful-api-guidelines

    1 like · 142 views

Achievements

Awards earned by the repositories zalando owns. Select an award to embed its badge.

No awards yet

Repositories earn awards by reaching the top three in a completed trending day or week.

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.