AWS Lambda is a powerful service that provides a hassle-free way to run our code in the cloud without needing to concern ourselves with the underlying infrastructure.
At Taxdoo, we rely on Lambda for a vast array of services, as it streamlines our development process and ensures our focus remains on delivering innovative solutions.

However, while Lambda is an ideal choice for many use cases, it’s not always the perfect fit. There are times when a more flexible and customizable approach is necessary, such as when dealing with long-running tasks or more complex workloads. In these situations, containerized solution shines as a robust and scalable container orchestration service that can accommodate a wide range of needs. By moving from Lambda to the containerized solution, we were able to achieve greater control and flexibility while maintaining the efficiency and convenience we’ve come to expect from AWS services.

Recently, we encountered a well-known limit of Lambda functions, which is why they have a 15-minute execution limit. Over the years, as Taxdoo has grown so has the amount of clients we need to prepare invoices for. This task used to take a few minutes to complete, but not too long ago, we quickly encroached on the 15-minute time limit. 

We needed to move our workload to an AWS service which didn’t impose a 15-minute execution time limit. We needed something that could be set up fast and required very little maintenance.

Furthermore, we considered moving the workload to an EC2 instance but quickly dismissed the idea as the workload only runs a few times monthly and also runs for around a maximum of 30 minutes. While we could have spawned an instance as needed, doing so would have burdened our team unnecessarily. Furthermore, we preferred to continue using CloudWatch rules for scheduling and invoking our workloads, which can be complex to manage with EC2.

Moving from AWS Lambda to a containerized solution, we chose to use AWS ECS, a fully managed container orchestration service that simplifies the deployment, management, and scaling of Docker containers on the AWS cloud using EC2 instances. Here are some of the key benefits of using ECS over EKS that we found:

  1. Simplified management: With ECS, we were able to simplify the management of our containerized applications. ECS is easier to set up and manage compared to EKS, especially for those who are new to Kubernetes. EKS requires more investment from a technical perspective and base cost perspective.
  2. Better integration with AWS services: As an AWS customer, we found that ECS integrates more seamlessly with other AWS services like CloudWatch or CloudFormation This made it easy for us to build, test, and deploy our containerized applications using familiar AWS tools.
  3. Focus on our application code: With ECS, we were able to focus on writing our business logic instead of worrying about the underlying infrastructure. ECS provides a managed Docker environment for our containers, which meant we didn’t need to spend time setting up and maintaining our own cluster inside AWS.
  4. Cost-effective solution: We found ECS to be a cost-effective solution for our container orchestration needs. We didn’t need the same level of infrastructure or any expertise in Kubernetes as it would be needed for EKS, which helped to keep our costs down.
  5. Highly scalable: ECS is highly scalable, allowing us to quickly scale up or down based on the demand of our application. This ensured that we could deliver the best performance and experience to our customers.

Overall, we found ECS to be a great choice for our company when moving from AWS Lambda to a containerized solution. It simplified our management, integrated better with AWS services, allowed us to focus on our application code, and provided a cost-effective and highly scalable solution.

ECS allows us to run our tasks on EC2 instances which ECS provisions for us as and when required, but it also allows us to run our workloads using Fargate. Fargate allows us to run our ECS tasks and services on AWS-managed servers, similar to Lambda. 

When comparing an ECS Fargate task to Lambda, it’s important to note that the primary distinction is that an ECS task requires a Docker image, whereas Lambda can run a variety of programming languages natively (as well as Docker images, if desired).

Initially, our service was intended to operate within a Java lambda function. In order to transition to a containerized solution, our first step was to create a Docker image capable of running our task. To achieve this, we made only a minor modification to our task code by implementing a main method that could be linked to a Docker image. Fortunately, we found that a simple and straightforward vanilla Java Docker image in which we simply referenced our output jar file was more than sufficient for our needs.

				
					FROM openjdk:19-jre-slim
COPY project/path/code.jar /docker/path/code.jar

ENTRYPOINT ["java","-jar","/docker/path/code.jar"]
				
			

In order to run ECS tasks within an ECS cluster, we need to create a task definition. We did this using AWS CDK. One particularly useful method offered by the CDK was `ecs.ContainerImage.fromAsset` which did three things for us:

Build the docker image for us, push it to a managed registry for us, and link it to the task definition we’re defining.

				
					const createEcsFargateTask = () => {
  const taskDefinition = new ecs.FargateTaskDefinition(
    this,
    `yourTaskName`,
    {
      cpu: ...,
      memoryLimitMiB: ...,
      taskRole: taskRole, // role which is executing the java code
      executionRole: executionRole, // role which is triggering the ecs fargate task itself
      runtimePlatform: {
        // define runtime here
      },
				
			
				
					 }
  );

  taskDefinition.addContainer(`yourContainerInstanceName`, {
    containerName: 'yourContainerName',
    // import docker image here for the container
    image: ecs.ContainerImage.fromAsset('..', {
      exclude: [
        // good for excluding unused modules
      ],
    }),
    environment: {
      // set environment variables here
    },
  });

  return taskDefinition;
} 
				
			

Code we added inside our CDK configuration

And just like that, with a simple update to the target for our CloudWatch rule, we bid adieu to Lambda and welcomed our application into the world of ECS. Migration complete!

Software engineering is all about coding. Right?

Wrong. Well, just a little bit at least. Software engineering is way more than writing lines of code. Problem-solving, understanding complex business systems, specifying the scope of project implementation, defining contracts between clients and customers, coordination (for resource allocation, deployments, interlinked pieces of work), prioritizing, communication between colleagues or with Product Managers… the list goes on.

In fact, for many developers, coding is the easy part. You can practice this craft to perfection. Got a bug? Fix it. Data table locked and clients can’t log in? Declare an incident and fix it. Deployment of a new release failed? Fix it.
We, developers, are innate fixers. Logically minded, we love building solutions that help someone in some way. Which in itself is an innately empathetic trait.

Yet, when deadlines are tight, or the team is stretched too thin, or even when everything is going brilliantly, we can sometimes forget to work on the long list of other skills we need to do our job which doesn’t involve code. This is where having good Emotional Intelligence is incredibly valuable. Not only for yourself but a survey of hiring managers confirmed that 75% of hiring managers valued high EI over high IQ.

Firstly, what is Emotional Intelligence?  As April Wensel said in her talk at PyTennessee in 2018, it’s not about sugarcoating difficult conversations or being an extrovert. Emotional Intelligence is about not being ruled by your emotions. 

American psychologist, Daniel Goleman, popularised emotional intelligence and defined five key principles that underpin EI; self-awareness, self-regulation, motivation, empathy, and social skills.

How can we apply this as software engineers? We’ve broken down the five EI pillars into simple definitions and, based on extensive research and lived experiences as developers, we’ve collected some examples and tips that you can use to boost your Emotional Intelligence.  

Self-awareness

Self-awareness is being able to understand your emotions and how your reactions to your emotions affect others. As a developer, it’s good to spend time reflecting on your intrinsic strengths, weaknesses, environments that you have a natural preference for, and potential situations that can trigger you. A good example of having good self-awareness is knowing how much you can do.

It happens often in teams of developers that a sprint finishes with initially committed user stories unfinished. Self-awareness enables the team to take on and commit to finishing a realistic amount of work based on the complexity and skill set of the team. An example of this may be considering whether, even on a good day, could you complete an 8-point piece of work within a working day. It’s unrealistic to commit to this if you know you would struggle or have never completed a piece of work like this in that time.

How can self-awareness help you as a developer? In a nutshell, it will help you to recognize and mitigate the impact of stress by understanding your skills and limitations accurately.
From tight deadlines to receiving constructive feedback in 1-1s to tackling criticism during code reviews to simply working in the fast-paced world of software development, the ability to recognize when you are experiencing stress will help you to limit the impact it has on your health and develop healthy coping mechanisms.

To boost your self-awareness, ask yourself the following questions and journal your answers.

Complete this exercise once a month and review your answers from the previous month.

Do you notice any differences?

Self-regulation

Self-regulation is the ability to manage your own impulses, energy, and moods and to think before you act. This is particularly useful when you apply this to managing your capacity at work and how you react in a professional environment. We probably all know the impulsiveness that comes with working behind a computer screen; less actual face-to-face time, brisk deadlines and the sometimes unavoidable insularity of coding can mean that you can get stuck in your head and forget how to regulate yourself when it comes to interacting with other human beings.

For example, let’s say we’re a junior developer who has just started learning Java. They see a high priority ticket in the sprint, weighted at around 8 points. We all know the feeling. We want to impress and please our team. But we don’t have the skills needed to complete the work, especially in a specific timeframe. Self-regulation, in this case, will mean that you decline to pick up the ticket but maybe offer to pair or review the work of the more senior developer who picks it up. Sure, you’re turning down an opportunity to shine but you’re also not being controlled by your pride and accepting work which will be stressful to complete well. Instead, self-regulation helps you to make a decision that is realistic and benefits the team, as well as the business you work for.

This might present as getting irritated at correcting a colleague’s code format for the umpteenth time (despite also asking them to install a linting extension in VS Code) and writing a slightly too direct comment on their latest merge request. With a few grumpy exclamation marks to boot.

When you are unable to self-regulate, you react in ways that are driven by your emotions, which isn’t always appropriate in a professional setting. Outbursts like the one above are likely to make your colleague more hesitant to ask for your help when they next have a merge request to review, for fear of getting the same reaction. Over time, reactions like this lead to a less collaborative environment. Had you been able to self-regulate and calmly explain why the changes needed, your colleague would’ve made the adjustments and would trust you as a source for support in future.

Motivation

What motivates you? Many of us working in tech are lucky to be well paid, have interesting projects, a work-life balance, and have supportive colleagues (or, at least a mixture of some of these).
But does any of this motivate you intrinsically

It may well be that none of these motivate you, which is OK. Understanding what drives you will help you write and keep writing the best code you’ve ever written. If the going gets tough, you’ll already know how to tap into your innate ambition and stay focused and positive. You’ll also be more likely to take the initiative to take charge of your own career and create your own opportunities, as opposed to following the path set out by your employer or what is expected of you by others.

This is not about promoting ‘hustle culture’, but more to highlight the importance of knowing what keeps you going and cultivating a proactive mindset which means you are ready and motivated when opportunities that align with your goals present themselves.

Empathy

Empathy is the awareness of the feelings, needs, and concerns of others. Being aware of how others experience the world means that as a developer, you are better able to communicate and build relationships with lots of different people.

Take our example earlier of writing an irritated comment in response to a mistake on a merge request. When exercising empathy, you may consider whether your colleague has made a mistake because they are stressed or whether code quality standards are communicated clearly across the department. You would then share your feedback on the merge request calmly and perhaps check in with this colleague.

To be clear, empathy is not about lowering your standards or cutting people too much slack. It’s about considering others and considering how your actions may impact them. A good example of exercising empathy is setting easy-to-understand variable names. Underpinning a key principle of clean code, setting variable names which are easy to search, intentionally named, and describing the logic of the variable makes life much easier for the next developer who comes along and has to work out what the code does. This contributes to how easy a system is to maintain or re-architect. Ever designed an API? Developers are your users, so develop and publish an API and related resources that are simple and if possible, include a feedback option so your users can ask questions. At Taxdoo, we offer Developer Support for our API via Reddit, so that developers can read discussions and share knowledge.

Ever heard of Ubiquitous Language? Eric Evans coined this term in Domain Driven Design to describe the practice of establishing a language between users and developers, based on the Domain Model. By using empathy to develop Ubiquitous Language, we then have a framework of communication between developers and business domain experts that makes the feedback for testing or developing a product clearer and much more impactful.

Being aware of how others feel is also key if you aim to become a leader. People gravitate towards those who can unite a diverse group of people and bring out the best in them. Highly empathetic people are also more likely to be able to acknowledge and successfully navigate political situations at work in a way that delivers results, for example, securing promotion for a direct report or receiving more resources to better complete a project, without compromising their integrity or neglecting the development of their team.

Social Skills

Social skills are just for social butterflies and extroverts? Of course not! Even for the most shy or introverted, social skills can be developed in an authentic way so that you can connect and work with others. Social skills cover a breadth of qualities; the ability to communicate (think honestly and clearly, rather than chatty and convoluted), the ability to build trust and bonds with colleagues and most powerfully, to yield influence based on the high regard that your colleagues hold you in.

Let’s uncover another myth: having good social skills is not about being popular or striving to make everyone like you. Social skills are about presenting yourself authentically, being an uncomplicated person to work with, and being someone who can mentor, manage and resolve disagreements in a way that builds trust, rather than erodes it. In many organizations, people who possess brilliant social skills can also use this to spark change in a positive way. Does the company want to become agile? Advocates will be selected based on their sphere of influence to spearhead a cultural shift and ensure that the adoption remains high.

At the end of the day, we know that Emotional Intelligence is often overlooked as a ‘mere soft skill’. We like to measure success with cold, hard metrics. So why care about Emotional Intelligence, especially in a logic-driven field such as software engineering? Because a high IQ alone is not enough to achieve success.

Much as we are expected to have multiple skills and areas of knowledge as an engineer, to work sustainably and be more impactful, we need to address how we behave, react, and present ourselves at work. The great thing about EI is that it puts the focus back onto personal growth, emotionally and mentally, as opposed to professional growth, which focuses on acquiring new skills and experiences to remain competitive. 

Combining both and suddenly, we, as engineers and tech professionals, can sustainably deliver value as well as grow as individuals. 

Not sure how to approach this subject with your team? Share this article with trusted colleagues on chat messenger, ask them to read it, and see what they think. Perhaps it will spark a healthy debate on what processes a team or department could work on to promote a culture of emotional intelligence.

Or if a problem keeps arising around code reviews or difficult-to-understand documentation, use this article as a conversation starting point for addressing these issues in retros or post-mortems. It is good to note that in some organizations which are purely results driven or where mental health or wellness at work is not prioritized, that the topic of Emotional Intelligence may be viewed negatively or could cause someone to take offense. Not everyone thinks the same or is as progressive as you’d hope them to be, so consider before you decide to raise this topic in your workplace.

We hope that you found this article. Please feel free to share your feedback or experiences with us!

Maria, Engineering Manager at Taxdoo, delivered a presentation on Emotional Intelligence in Software Engineering at the FemTech Conference in 2023. Covering the definition of Emotional Intelligence, management psychology, the professional benefits of high Emotional Intelligence to practical tips on how to improve your own emotional intelligence, her talk was a deep dive into EI that aims to provide practical ways to improve your own EI whilst supporting your team in an EI-positive environment.

What is Domain-Driven Design and why is it helpful?

Domain Driven Design (DDD) is an approach to software development, made popular by Eric Evans’ book, Domain Driven Design, published in 2003. It still receives a lot of attention today and is a highly respected tool in a lot of architects’ toolboxes. 

Why? Quite simply, DDD is about guiding engineers to focus on the business domain (e.g. the terms, rules, and business goals that business experts apply to a given problem), rather than technical concepts or frameworks, and to collaborate very closely with domain experts to find a shared language and model for the domain.

Over recent years, DDD has proved incredibly useful where software businesses scaled fast and developed a need for vertical cuts through their products, teams, and codebase. For example, the rise of microservices requires tech teams to define modular boundaries and assert which logic belongs to which service. DDD is also helpful in creating a product that is aligned with business priorities with fewer iterations, as it focuses on closing the gap between the code and the reality of the business needs.

At Taxdoo, we focus on the domains of Taxes & Accounting. We tend to deal with complex software where the limits of our understanding can soon become limits of our products and codebase. Luckily Taxdoo offers us to spend 10% of our time as ‘innovation time’ where we are encouraged to learn and experiment.

Making use of that, a few of us engineers and domain experts founded a book club, where we spend our innovation time reading and sharing what we’ve learned together.

There’s no such thing as too much collaboration.

With knowledge sharing, it can be tempting to have only software engineers at the table. We’re learning about a coding concept, so why involve other parties?

Having domain experts in the book club prevents engineers from becoming too technical or jumping into ivory tower discussions. 

At Taxdoo, we involve domain experts, called ‘Regulatory Analysts’, in our book club reviews and also our scrum ceremonies.

The result? We are using and constantly optimizing a shared language and mutual understanding about the rules and terms of our business that we use in our daily work and can be applied in our daily work. A huge bonus of involving domain experts so closely is that user stories are written by a domain expert, which reduces ambiguity and deviation. It took some time before both parties learned the terms used by the other, however, it has resulted in greater transparency and clearer requirements.

Business Process Model notation (BPMN): where analysis and implementation go hand in hand

Another interesting learning is that DDD discourages a separation between analysis and implementation.

Often, engineers collaborate with domain experts only until they think they understand the problem. Then they go and write the code, so that the implementation is hidden in the code and invisible to the domain experts. This then necessitates a step of translation, done by the developer, that often unconsciously changes domain logic or language. This drift in precision causes technical debt or bugs as the project progresses.

In Taxdoo, we use decision trees for our tax logic, and in the past, these trees were provided as diagrams by domain experts and then translated into code by us engineers. This approach was fine, however, we still weren’t quite accurate enough in communicating and understanding our requirements.

Last year we migrated this logic to BPMN, which is an industry-standard for business process modeling. The great thing about BPMN is that it combines the diagram and the implementation. This is done through an underlying XML layer. We can now collaborate by visually creating a diagram together and do not need an additional implementation that could impose the risk of misunderstandings or drift in language.

There’s still a long way to go, however moving to BPMN was a great start to close the gap between analysis and implementation.

Value Objects: capturing values in a transient state

DDD is a large concept that can be adopted on all levels of a company. That being said, not all companies have the capacity for this and in any case, it makes sense to experiment with concepts before applying them on a large scale. One application of the suggested code patterns that worked very well for us was the introduction of Value Objects.

In DDD, Value Objects represent values in a transient state, usually bound to one operation. They are distinct from entities, which are longer-living objects that have their own lifecycle and identity in the given context. In contrast, value objects don’t need any kind of identity, because two instances with the same values could be used interchangeably. 

Here’s an example where we introduced such an object and how it helped us:

VAT IDs

The VAT identification number is assigned to a company by the financial authorities and used for value-added tax (VAT) purposes.

In our world of B2B taxes, the VAT ID is a type of value that we need to process often. When a customer provides us with a VAT ID through a form or support requests, we usually receive it as a simple String. A first improvement to the object (to make it a more powerful part of the domain model) would be to restructure it in a way so that it yields more information about its purpose.

While this refactoring is not really providing a lot of additional logic, it already helps to fulfill the claim of DDD refactoring: “Refactoring towards a deeper insight of the domain”. By making this value a dedicated class and destructuring the characters into fields, the code becomes clearer about the contents of the VAT ID String, which is especially useful if you’ve never seen a VAT ID before.
We could now also add validation to make the object even more helpful.

For Taxdoo’s use case, there’s a little more to it: a VatId country code is usually the IsoCountry code of the country where the company has registered. However there are some edge cases. In Greece, the country code for VatIDs is “EL” instead of “GR” and Northern Ireland also has its own country code of “XI” even though its usual IsoCountry code would still be “GB” for Great Britain. 

To encapsulate that domain knowledge as part of our implementation, we can add a dedicated Getter that would translate the encoded country code into an IsoCountry:

By combining this domain knowledge we can provide an even more reliable parsing and validation. We know that the country code must either be castable to an IsoCountry or match one of the special cases mentioned above. If the provided country code prefix in the input String does not match these conditions, we know that the provided VAT ID is malformed:

In summary

Let’s recap: initially, we had a simple value, stored in a String. In the domain of tax evaluation, that value is often processed, parsed, and interpreted. We need to check for the validity of the VatId, we need to derive information and we need to send it across the network.

By making it a dedicated class, we strengthen our understanding of what a VatId is. If a new developer comes into our Taxes & Filings team and sees this code, the code represents the domain model that is useful when applied to our context. A lot of these principles could simply be regarded as “good OOP” or best practice, however in this case it helps us to understand the domain and share the attributes and capabilities of our models with the domain experts. 

In a real-world use case, there’s much more knowledge that can be contained in a VAT ID model inside of the context of taxes: Is the VAT ID valid? When was it registered? Note that depending on the context, the VAT ID could receive an identity with its own lifecycle (it’s even called ID!). In such a case, it would not be a value object anymore but would become an Entity, because we would store it with an identifier, so that we can track its lifecycle and add relationships to other objects, for example, a “Company” object.
Thinking about your objects and if they need a lifecycle in your domain will help you to obtain a deeper insight into your domain. This is a great tool from the DDD toolbox.

Layered Architecture

Our final example: the isolation of a domain layer in the code base. While we applied this as part of our interpretation of Clean Architecture, the isolation of a domain layer is part of the layered architecture that is suggested by the book.
We did this by creating a dedicated package for the domain logic and extensive use of Java Interfaces whenever we wrote code that was related to persistence or other infrastructural tasks. The domain package contains the long-living domain logic (e.g. applying the tax evaluation), while database transactions, API clients, or serializers are hidden behind interfaces with their implementations in a separate data package. The resulting package structure looks like this:

This separation allows us to make changes to the infrastructure (e.g. moving from RDS to DynamoDB) without touching the domain logic since we only need to provide another implementation of the respective interface. At the same time, we can also test our domain logic (which is the most important one to test) without worrying about the setup of a database or external service. It’s also easy to check or lint: No class in the domain package must ever contain an import from the data layer.

4 Tips for Getting Started with DDD in your Organisation

  • If you want to promote DDD or learn more about it in your company, involve domain experts from day one. They will prevent you from drifting into technicalities and you will collectively learn a shared language to discuss your daily collaboration.
  • Getting started with DDD works especially well when you work with serverless architecture (like Taxdoo) since architectural changes can be done faster compared to on-premise (which means that servers would be hosted physically by the software company itself, requiring time and financial resources to maintain their own infrastructure and server hardware) and the architecture is divided into smaller components. You’ll also spend less time on maintenance of non-domain-logic components since most of that is handled by the cloud provider.
  • Leave the larger and more complex patterns (for example Aggregates and Factories) for later and concentrate on the core idea. You don’t necessarily need to rewrite all code, to start your shift towards a more vivid domain model, but you can do that e.g. through the introduction of Value Objects.
  • If you haven’t done that, you can also start by isolating a domain layer first. Once that is done, you can apply more of the DDD patterns inside that layer, if it seems reasonable for you.

Good starting points for further information would be the “Blue Book” or the summary in the form of the DDD reference, both by Eric Evans. If you prefer to watch conference talks, I can also recommend checking out the DDD Europe Youtube Channel which contains a lot of talks around DDD concepts or their (technical) implementations.

Do you have experience with DDD? What were your takeaways from it? If you are new or are leveling up your DDD knowledge, we hope that you found this article helpful. Please feel free to re-share this post on social media or amongst your connections.

Finally, this blog post would not have been possible without the help of Paul, Maria, Alex, and Kevin. Thank you for the book club sessions that we had, and for your thoughts and inspiration!

In Taxdoo you’ll find the room and other motivated colleagues to invest time into new concepts and experiments. Join Taxdoo if you would like to participate!

Moving to management is fun when you know what it takes

It’s not easy being an Engineering Manager and it takes more than just a good work ethic. The first step in becoming a good leader is learning about yourself as an individual. Self-awareness and self-reflection are key if you want to be an empathetic and confident leader. Once you know what it means to be you, it will be easier for your direct reports and colleagues to figure out how they relate their own strengths and weaknesses with yours. They must be able to see how their work contributes to the whole and feel valued as members of a team.

What makes a good engineering manager at Taxdoo? With our Taxdoo values and culture in mind, here are some tips on becoming and excelling as an engineering manager. 

Motivation

One of the most important things you can do to become an engineering manager is to keep yourself motivated. And understand what motivates you. Motivation is a mindset that keeps you one step ahead of your competition and allows you to achieve more than what would seem initially possible. 

In order for motivation to have an effect, the first thing to do is to make sure that there is a clear goal or set of goals that need to be accomplished. From there on, it’s easy. Make a plan with small actionable steps that are part of the overall goal. Once something gets accomplished, ticking it off marks an incremental step toward completing your goal. Not only does it feel good to work in this way, but it also strengthens the resolve of yourself and others as progress is tangible and constant.

Empowering Others to do their Best Work

A good engineering manager knows that empowering their team is their primary role.

Good leaders celebrate and hone the unique capabilities and personalities of their direct reports and strive to support each individual to grow whilst delivering business value. By trusting their team to self-organize with day-to-day operational tasks (such as attending stand-up or organizing code reviews), an engineering manager can then focus on coaching engineers and inspiring them to do their best work by gradually assigning them more significant pieces of work which challenge them and with guidance, push them out of their comfort zone. 

Feedback is key

Constructive feedback is key to the success of your team. It’s about giving your team members the information and guidance they need so they can succeed, but also being humble enough to accept feedback from your team or your own manager. At Taxdoo, our culture fosters frequent feedback and this is one of the things our future engineering managers need to encourage as a constant.

To us, feedback is the cornerstone to creating a culture where mistakes are embraced and a growth mindset is celebrated. And encouraging our engineers to be brave enough to take action rather than avoid risk. It means setting up systems for continuous improvement and feedback loops between leadership and employees so that everyone knows what’s expected of them in each role on the team, or across teams. If you’d like to find out how we embed this from day one, check out our Onboarding blog post.

Celebrate mistakes

It’s important to remember that mistakes are encouraged when you’re an engineering manager. Think of it as an opportunity to learn and grow. No one’s perfect, so why should you or anyone else be punished for it?

In an engineering setting, we all know that the business of shipping code can be a risky business. Deployment failed? Major outage? Stay calm and fix it. Then assemble your team for a blameless incident post-mortem. Take the lead and share the results with the engineering department and the rest of the business. No one is more stressed than your engineers when something goes wrong; it’s your role as a manager to steady the ship, investigate what happened, support the solution, and show solidarity with your team in front of the entire business. This fosters psychological safety, which will unite your team when times get tough.

At the end of the day, we work in tech, not the emergency room.

Communication solves everything

Communication is so important when building a team. Something that people often miss though is that communication isn’t just about talking; it’s also about listening.

Communication in the workplace is essential because it facilitates collaboration in an environment that brings a diverse range of people together and helps them to harness their unique abilities to achieve success on projects and tasks that are important to the company. Collaboration is something we cherish deeply at Taxdoo. We believe that it allows everyone to simultaneously experience how their work impacts other teams, and how other teams’ work impacts their own. This builds awareness and makes the path to success smoother than ever.

Everyday is a school day

It’s important to keep learning, especially in a fast-paced environment like ours. You can learn from your team, and they can learn from you. Everyone has different strengths and weaknesses, so it’s best to understand each other before jumping into a critical piece of work.

For example one person might be great at writing code but not so great at understanding what their teammates are talking about; another person may have a very strong background in programming but not so much experience with business management.

We could go on and on, but the point here is that everyone has something unique to offer—and those differences should be valued as much as their similarities!

Learning is a lifelong process. You can’t stop learning and you never have to stop learning. The best thing about it is that it’s not just about reading, watching, or listening; it’s also about asking questions.

Learning isn’t something that happens once in your career—it’s a process of trial and error. Try new things and fail at them until you figure out why they didn’t work for you before giving up. Alternatively, you can try again with another approach or strategy to see if that makes sense for you as an individual, team member, and employee at Taxdoo.

At the end of the day, what you do matters more than what you say

As a new leader, you’ll face challenges that will push your boundaries and stretch your skills. You’ll have to learn new things and put them into practice, including how to empower effectively, motivate others, and communicate with the people on your team. Becoming a good leader is hard work.

If you’re interested in having a role that enables you to make an impact and grow as an individual as well as part of an organization, there’s no better time than now.

While becoming an engineering manager isn’t always easy, it’s definitely rewarding. The benefits of leadership are endless, and you’ll be glad you took this step when you see how much your team grows.

This article is written by the engineering managers at Taxdoo. 

André Kowalewski, Katarina Lang, Zeynal Zeynalov, Maria Canero, Alexander Klein and Gabriel Guimaraes.

Hi, I’m Hendrik, a JavaScript enthusiast and Engineering Manager at Taxdoo. Today I wanted to take you on a journey of exploring what technical debt is and how we deal with it here at Taxdoo.

Working with Engineers you probably heard the term “Technical Debt“. But what is this “debt” Engineers keep referring to? Just an excuse to push features further out? Join us on a journey to understand what Technical Debt has to do with doing your dishes and paying back your student loans.

What is debt?

> Something that is owed

In its most basic form, Debt is simply something that is owed to another. The most common debts we owe are:

– Money 💸, that we owe to a bank or student loan.

– A favor 🤝, that I might owe to a friend who helped us move apartments. 

This is what we most often think about when the word “Debt” is mentioned. But there is another kind of Debt that we all face in our daily lives. I like to call it “Dishes Debt“.

Why doing your dishes is important

Most of us use our kitchens every day. We go in, prepare our food, and then leave. One might say:

> Your kitchen provides value to our lives by allowing us to cook with all the appliances we need.

However, this ‘value-creation process of cooking food always leaves behind dishes that we have to wash before more food can be prepared. As a fan of one-pot meals myself, I know my big pot of pasta requires washing right after I finish it.

This is how I came up with the term dishes debt. Dishes debt is exactly that moment in time when I realize I have to do my dishes first, and only then can I allow the kitchen to deliver its core value of allowing me to cook my food.

> Occasionally the value-creating process of cooking produces Dishes Debt that has to be paid down before more value (food) can be created.

We find the same kind of principle at work in Engineering. We call it technical debt.

Technical Debt

In Engineering we as Engineers:

> Provide value to our customers by coding features for our products.

As engineers, it is our responsibility (and passion!) to provide value to our customers by coding the right features for the products we are working on. Similarly to how the kitchen provides value when it comes to food preparation, we engineer products that make our users’ workflow a pleasant and easier-than-ever experience. Of course, as with every process, engineering also leaves behind some byproducts that need to be taken care of before we can create more value.

> Occasionally the value-creating process of coding produces debt that has to be paid down before more value (features) can be created.

Remember the one-pot pasta dish I was talking about? Well, in engineering terms, this is her again.

That being said, the point where we have to do some coding before implementing new features, we call Technical Debt. The only difference here is that as your dishes pile up next to your sink, you can see them, count them, and make a plan of action. Technical debt, on the other hand, is not as tangible, which is why it takes some extra effort from our side to pay it back.

Before we continue to see how we can implement the best strategies for dealing with technical debt, let’s first learn what types of it exist out there.

Types of Technical Debt

At Taxdoo, we divide technical debt into three categories: deliberate, architectural, and entropy. Let’s dissect each.

Deliberate Technical Debt

Deliberate technical debt is one we take on knowingly. We either see it coming intuitively, or we’ve done something similar in the past where debt arose and we can just feel it in our guts. A sentence you hear us say most when deliberate technical debt is involved is “We need to deliver this now”. For the sake of making a deadline, we then cut corners.

> We know there are problems but we accept them to deliver something on time.

These problems we accept or corners we cut come in different shapes. They include “hardcoding” connections, maybe for now you can only filter a table of offices by a hardcoded list of cities while we know that in the future that list of possible filters should come from the list of all offices.

Architectural Technical Debt

In engineering, managing expectations is no easy task. Even more difficult is when we have to accommodate them. This is when architectural technical debt steps are the work we need to do to accommodate these ever-changing expectations.

> The system was not built to support this.

Whether we didn’t know about an important use case before commencing work, our original assumptions were wrong, or our company pivoted, all of a sudden our work becomes more difficult. Now, with all the other things we need to do, we also have to do some refactoring. Often we find ourselves asking the question: What do we need to change in the way we support the current use case to support the new use case?

This type of Technical Debt often arises in the conflict of creating a “solves all problems” vs “solves exactly our problem” solution. A highly-adaptable product might take a bit more time now but pays back with its flexibility later. Something more targeted is faster to accomplish now but will require a lot more work to become adaptable later.

Entropy Technical Debt

Entropy is the fact that:

> Over time the quality of everything you don’t consciously maintain deteriorates.

So many things add entropy to the work of engineers that it’s difficult to even start listing. New team members cannot know the full history of our code, for example, and will naturally work differently. Architecture and requirements change, and sometimes already utilized technology becomes outdated. It’s part of the game, and entropy technical debt is at exactly this intersection of time and relevance.

Washing the dirty dishes

Now that we can understand the different types of technical debts, it’s time to learn how to tackle them. We will do this by once again looking at the dishes debt and how we often overcome it.

Some of us (and I might be included in that) clean just what they need. Like my pot for porridge that I often wash in the morning to make today’s batch.

A trained chef-turned-programmer I used to work with was quite passionate about this one. He taught me that no professional kitchen could run if it didn’t take care of the dishes while cooking was still in progress.




Habits are great, they become involuntary actions that we don’t think about, we just do. And doing dishes every day makes sure we clean small batches that are easy to handle, enabling us to use all our dishes every day.

Sometimes there is nothing else you can do. For days you didn’t pay down your dishes debt and now you can’t see the countertop. You’ve got to put in that hour of effort and do everything now.

Maybe you can even find a way to not have as much dishes debt. Ordering take-out every day could be an option but it produces a lot of waste and is much more expensive. An innovation could be a dishwasher: it’s a bigger, one-time investment but now you don’t have to do the washing anymore, and it can handle a lot in one go.

Technical Debt strategies

The best part is that we can translate our dishes’ debt strategies to pay down our technical ones. Let’s change up a few words together, shall we?

Picture it: there is a new feature coming in but some technical debt is holding us back. No other choice but to fix that first. Only if we had fixed it on time… Now our system wouldn’t be so hard to maintain, estimates wouldn’t have blown up more, and Software Engineers would be at least a tad happier. What a dream.

In Software Engineering we often employ something we call code reviews. In a Code Review, peers check each other’s work and give ideas on what could be improved. Apart from being peer-to-peer learning opportunities, code reviews are also a natural place to catch Technical Debt before it makes its way into our main codebase.

Another great example of doing dishes while you code is often referred to as “scout mentality” – always leave a piece of code you touch cleaner than it was before. To reflect this, some teams always add a fixed percentage of “scoute time” to their estimates.

We at Taxdoo allocate 10% of our time towards technical innovation and learning. This time-budget is up to Engineers to spend.

And for the other 90% of our time, we make sure to prioritize both feature improvements and technical work.

Sometimes you either need to fix your technical debt now because your systems are failing, or there is no feature pressure right now, so your team can take their time to perfect the technical implementation.

For us this sometimes takes the form of taking a whole sprint just dedicated to fixing and improving things.

A great way out of technical debt is to solve the old problem in a new way. If updating the system always takes longer, maybe you can build a configurable system that can get adopted faster and erase the existing technical debt, thus making Engineers happy.

We drive innovation both as part of feature work and in the 10% innovation and learning time that our Engineers get. It makes me extremely happy to say that it has resulted in amazing improvements!




Preventing technical debt

Although we apply the above-mentioned methods to reduce our technical debt, there still are some residues. There probably always will be. This doesn’t mean that we still can’t take more measures to prevent some of this debt from arising, though.

The right tools can already catch some of the debt in the act. Using TypeScript over JavaScript, for example, will help you detect some of those runtime errors during the stages of development. Observability will make you aware of problems while they are still easy to fix. What a relief!

Realizing that debt is something we are likely to incur enables us to consciously take on debt where it helps us to move the business forward and turn it into a part of our prioritization.

Final thoughts

Writing code is a complex problem. Software Engineers constantly need to decide on trade-offs between “thinking about everything up front” – so that we will need no adoptions later – and “building what is needed right now” – so that we are fast. Both are right at times, largely depending on how easy the system is to change later.

When considering technical debt in the context of planning time for implementation we have only two options: either to invest time in preventing debt to arise, or invest time later to pay down the debt created. In either scenario, we need to look at our priorities and make sure we are making an informed decision.

But, and it’s a big but, if you ask me, it’s always worth investing in debt prevention whilst paying down your current debt. Doing this makes sure that your company can react to sudden market changes and not be held back by unfinished business. And we all know it: in a sea full of fish, being quick to react is the most important factor that sets you apart from the rest.

Working in tech is awesome, especially as a software developer.
The opportunity to build amazing products, being paid to learn and working with very smart colleagues are just some of the reasons why this profession is so rewarding.

However, software engineering isn’t always a walk in the park. Tight deadlines, adjusting to remote work, fixing major outages and generally, the velocity of the tech industry are some factors that can cause you stress as a developer. Therefore, it’s important to look after yourself and create simple, daily rituals that support a healthy working routine.

Ahead of World Mental Health Day on October the 10th, we asked our software engineers on how they take care of their mental wellbeing.

Here’s what they said

1. Fresh air

Our interim VP of Engineering swears by fresh air and regular doses of sunshine; living in Hamburg means that biking to work or going for a lunchtime stroll around the Alster is easy to integrate into your daily routine.

2. Meditation

Some of us have trouble not thinking about things, so meditation can help you put things into perspective and arrive in the current moment rather than being swept away by thought.

3. The Pomodoro Technique

This technique focuses on working in 25 minute sessions throughout the day.
This can be helpful for focussing efficiently and it encourages you to take regular breaks so that you avoid sitting for hours and hours without moving, drinking water or looking away from your computer screen.

4. Connect with colleagues

At Taxdoo, we encourage everyone to set up or attend ‘Donuts’ (informal online meetings), regardless of department.
Catching up with a colleague over a random Donut or setting up a Developer Donut is a great way to get to know your colleagues and helps you to feel connected and part of a team.

5. Take a break

Coding is awesome and the feeling of completing a task is great, however rest is also important. Why not use your lunch break to talk a walk around the block? You might be surprised at how refreshed you feel.

6. Find a job you love

We all spend a lot of time at work, so it is important to feel comfortable and motivated by your tasks, colleagues and environment.

How do you look after your mental health as a developer?

If you’re wondering what it’s like to work at Taxdoo, we can confirm that we’re hiring! For more details, check our jobs page or follow us on Twitter for more updates.

Today is World Youth Skills Day so we want to celebrate young people’s access to training and career opportunities by providing some inspiration for anyone interested in working in tech.

We asked our developers, product managers and even our CEO about the resources that sparked their interest in tech and helped to hone their skills; here are their recommendations.


Practise this

If you have 30 minutes a day, try completing a few exercises on FreeCodeCamp. This is a great way to learn to code in bitesize amounts of time.


Try this

A good starting point are the Hello World courses on Codecademy, which helps with learning tooling set-up and understanding how things work in that language. You can also test your knowledge by modifying the code and adding other statements.


Get stuck into this

A slightly more advanced course for learning frontend development is ToDoMVC, which also has a lot of other examples for each tech stack.


Build this

Learning by doing is the best method which this C# Unity Game 3D course from gamedev.tv definitely will help you to do so.


Read this

Clean Code is the classic book written by Uncle Bob, otherwise known as Robert Cecil Martin, who epitomizes the concept of clean code. From a product perspective, check out Lean Product Playbook.


Watch this

Silicon Valley (HBO)
our co-founder, Matthias Allmendinger, recommends this series as it sparked the entrepreneurial spirit that brought Taxdoo to life.


Eat this

Sushi. Ok, just kidding. Although our developers do love a good Bento box, feel free to pick your favourite brain food for learning to code. Happy hacking doesn’t happen on an empty stomach!

We hope this list was helpful! It is, of course, by no means complete- what else would you recommend for budding developers

We’re growing at Taxdoo! Follow us on Twitter or LinkedIn for the latest news and job posts from us.