Software development has a fundamental tradeoff: move fast and break things, or move slow but get them right. If you’re building a small side project with limited scope and complexity, the tradeoff of breaking things isn’t too impactful. It’s relatively safe for moving fast to be the default. But what about long-term software? Those which businesses and consumers will rely upon for years — when does this tradeoff start to affect the resilient and robustness of the software we are creating? Let’s take a look a what resilient code is, and when it’s the right time to write it.
Investment Now, Payoff Later
As software developers, it’s easy to think of development as an immediate jump from investment to reward — you’ve just built a feature, it’s now deployed; you’re done. From this perspective, it can be tough to justify spending the extra time to make sure you’ve coded something well.
It’s easy to say “if it works, it works” and leave it at that.
The reality is, code written quickly and haphazardly now can start to create problems down the track. As your codebase grows, complexities increase and abstractions multiply, so even small decisions can have compounding effects. The time-saving decision you made earlier might now be costing you in spades.
The Over-Optimisation Pitfall

You might instead try and swing the pendulum entirely the other way and sink a lot of time into setup early on: writing thousands of lines of code at the start of your project that don’t actually do anything yet.
And at such an early stage, you’re likely working with layered assumptions.
You might have an idea of what a future codebase will look like, but each step between now and then introduces its own uncertainties that might require a rethink of strategy. At that point, your setup cost has been both enormous and wasted as you refactor code you haven’t used yet.
In effect, the sweet spot lies somewhere in the middle. It’s all about knowing when it’s the right time to spend that bit extra into writing reliable code. So how do we know when the right time to write resilient code is?
The ‘When’ is Key; but When Is It?
The truth is there’s no definitive way to tell; for the most part, you’ll just need to wait for you ‘there has to be a better way’ alarm to sound. But there are some questions to ask yourself:
- Are you writing repetitive or obtuse code? Maybe you’re solving access control manually and are starting to feel the pain manually checking the user’s role on every route. Or duplicating a lot of code that should itself be a subsystem.
- Do multiple places have the same feature with different implementations? This can come back to bite you when you need to go back and update old code: how do you know you’ve changed all the places when there are more than one? This can quickly lead to annoyances and code fragmentation.
- Are your features or files getting bloated? If you open a feature’s file and shed a tear at the line count, it might be time to break up your code. Take subroutines or common sections and move them into their own functions, classes or components.
- Does updating one part of your codebase break something seemingly unrelated? Increased code coupling comes with increased risk of updates having a domino-effect on other parts of your code, which can be hard to find until runtime.
- Are you at the stage where the base system is complete? Now is a great time to start to include maintenance work in your development time, which should include increasing robustness.
- Do you just have to get it right? For mission-critical components where the cost of a systems failure is astronomical, spending the time up-front on resilience is likely a smart move.
What Resilient Code Looks Like
Now we’ve gone over why and when to write resilient code, the next logic step is what to do. An important thing at this stage is to limit scope creep, otherwise you might end back in the over-abstraction zone.
Resilient code comes in all shapes and sizes, but includes:
Gracefully handling errors

It’s frustrating to experience something that “just doesn’t work” with no feedback or error message. It then becomes a problem when users think they’re completed a task, but it silently failed. These errors can also be tough to track down — especially with transient failures that magically resolve themselves. The good news is both of these problems can be solved with graceful error handling.
The difficulty and effectiveness of managing unexpected errors depends on your programming language, this might be including try {...} catch {...} blocks into your processes, replacing .unwrap() with a match or map_err(...) call, or even just making sure a variable isn’t null before trying to use it for anything.
It can also be tough to manage processes which never complete. This could be external, like a web request from a third party which never responds, or a logic gap in your own system which causes an infinite loop or deadlock. In these cases, timeouts are your friend to cut-off the process before users wait too long.
Properly validating inputs
High quality validation libraries are becoming increasingly more common, and deserve a place in your codebase. Whether your framework has a built-in solution like Laravel’s built-in validation or third-party libraries like Zod, you should be using validation for all user inputs.
Because user inputs could contain absolutely anything, and you need to be sure they’ve given you something valid. And it’s one thing for innocent users to accidentally provide bad data, but another entirely for malicious actors to do so deliberately. You need to ensure your systems can handle whatever inputs users throw at you. Otherwise, you’ll end up spending more time fixing bugs and responding to security incidents than it would have taken at the start to get it right.
Writing Readable Code
Resilient code has a big emphasis on what your code does, but how it does it is equally as important. Consider going back to years-old code to make a change, but the system being so dense and confusing it’s hard to find what you need to edit — and even harder to make those changes without breaking other things.
Spending the extra time to write clear, readable code can reduce this problem significantly. Your goal should be to write self-documenting code in combination with hand-written comments for processes, edge-cases or extra context you could only get from being the one to implement it.
If you have overly complex systems, consider externally documenting how it works and linking to it in your code. This can especially help give an introduction to the system for new contributors or members of your team.
Test, Test, Test

Ah; tests. We all know we should write more, but we never do. But writing good tests is one of the most effective ways to write resilient code — make sure it covers all bases.
Your test coverage should be a guide, but it doesn’t tell you everything, especially the points where errors won’t be handled at all. For example, coverage is great for showing you that a catch {...} block is never hit, so you can write tests for that edge case. However, it cannot show you where you have missed implementing resilience.
So don’t just test the happy path; a significant number of your tests should be to ensure the system behaves correctly when something goes wrong. Try writing down all the edge cases you can think of, and since it’s 2026, ask AI to write you combinations of unexpected inputs to make sure it covers all basis.
So, What Is Resilience?
Resilient app development is more than just making sure you code works, but giving you a way to make sure it continues to work into the future. When you start shipping more than just a side project, it’s crucial that what you build works when it’s supposed to, and continues to work when something goes wrong.
Importantly, resilience is also about giving users a good user-experience. The key is to let users know when things go wrong and give them options on how to proceed. Even for external failures which you don’t necessarily have the capacity to solve, building in a fallback to display an error can help users understand that your product isn’t ‘just broken’.
Do you need software built for resilience? FONSEKA can help! We can build a custom application with resilience at it’s core, and continue maintaining it for years after. Get in touch at https://fonseka.com.au/contact
