How asynchronous communication can help in productivity

The time of the pandemic meant that a lot of us had to work remotely. For me it was nothing new, because I’ve been working this way for a decade. Nevertheless, the changes were very noticeable, especially in communication methods. Lot of people decided to move to online meetings and this has become the basis for many companies. Is it good? In my opinion and based on my experience, it depends. In many cases, especially if we talk about developers, it is not a good approach. Google example of a completely different solution is Basecamp: they have been using asynchronous communication for years and the company still exists without any issues. I also tried that and have to say, it works.

Synchronous vs asynchronous

First of all, we have to talk about differences between synchronous and asynchronous communication between people. It is very similar to communication in IT work: by synchronous we mean for example online meetings. Both sides can talk to each other, can discuss in real time, ask questions, get feedback and quickly make decisions. Asynchronous is a different approach, here emails are a good example: we do not know when exactly the receiver will read our message and will decide to send a response. It is something like a “fire-and-forget” rocket. We should not be interested in immediate action. It means asynchronous communication is slower, but also gives more time to both sides for reaction. 

Focus – key to productivity 

If we want to be productive, we should focus on important (and sometimes urgent) things. A lot of work needs deep focus, flow to be done in the right way. There is a problem with synchronous communication: in most cases it is like an interlude, distraction. With a lot of distractions – like smartphone notifications – focus work is not possible. Why? Many studies say that you can change your focus object just for a minute, but after that you will need more than 20 minutes to focus again on your previous work. Do you write a book, but decide to make a quick call with your friend? No problem, but you will need time to focus on your book again. Every time. The same is with “divisibility of attention” – some people say that they can do that, but studies do not confirm this. We can quickly switch context, but it does not mean that there is no price for that. Price is very high: we lose our concentration and cannot resolve complex problems. 

Unnecessary meetings

As I mentioned above, in theory synchronous meetings are better, because we can discuss issues and make decisions immediately. Unfortunately, it is only a theory and a rare case, only for very simple things. If we have to consider more complex topics, like software architecture, business dependencies, impact of the change on the current state, we will need more time. In such scenarios, I often had planned meetings just to ask me some questions. It was not possible to answer them immediately, I had to check some things, gather more information and then prepare possible solutions and… plan a second meeting for that. The question here is: do we want to resolve issues, create something amazing, or just spend more and more time on meetings?

In effect, such meetings only created chaos and destroyed focus – imagine you have just one such meeting in the middle of the day. It will probably block you from completing some things before, and also you will have to spend more time after meeting to go back to your work. Better option here is asynchronous communication, definitely. First side can prepare questions, check them deeply and send them to the receiver. Then the second side will have more time to check them, prepare all required things and… no, not make a meeting, but also send info to the first side. Additional advantage: both sides can reserve some time to handle received items. We should not interrupt our current work and do new things immediately, because then we will lose all benefits. 

Wrong approach to email

Different matter is email and how we think about that service. I remember that many years ago, before I worked on really interesting things, I liked browser extensions or desktop apps to check my email accounts and notify me about new messages. It was like an addiction, similar to the current situation with ex. likes on social media. New message = new notification = a bit of dopamine. Right now I do not use any desktop email client, and do not have notifications on mobile. It allowed me to resolve one issue, but second is how other people handle their emails. Some people are able to send email and… actively wait for an answer. If they do not receive an answer in a few minutes, they will use different communication channels to ask about the message. It is completely crazy – if you have urgent things to handle, do not use emails, simple.

Wrong approach to chats

Chats are similar, really. I remember times, when in Poland we used a local messaging app called “Gadu-Gadu”, it was in my school days and we used them only on computers because there were no smartphones. It was simple, because there was a clear “activity status” and we knew, when our friends were online. When smartphones started to be popular and developers created next and next messaging apps, things started to change. Right now, I often see people who think that chat should be synchronous. If I write to you, you should read that and respond as soon as possible. The question is: why? Who decided that? Did we sign any contract related to that? I really do not remember anything like that, so it is a bit strange for me. Such an approach can only bring a lot of frustration, especially for the sender: such a person will wait and lose a lot of time. Again, if things are super important and urgent (remember, most things are not!), just call, not write, because you do not know what the other side is doing at the same time. 

Even if you are “in the middle of a discussion”, you should not expect immediate answers. I know some very impatient people, they can send you messages and after a few minutes send… question marks, or “hello?” or something similar. It is also crazy and please – if you do something like that, stop right now. You will not make any friends with such an approach. It is much better to treat chats, apps like Slack, Discord, Teams or even messaging apps like Messenger, WhatsApp, Signal etc. as an asynchronous tool. More comfortable, but still asynchronous. Remember, that second side can just disable notifications for such apps or not use them – for example I do not use any messaging app on my phone, only calls and standard text messages (sms). 

When synchronous communication is better

Ok I wrote a lot about situations when synchronous communication is bad, but… we are people and synchronous communication is part of our life, so probably it also has advantages. Yes, definitely. It is the best choice if we want to collaborate, do the same thing at the same time. Real use-cases: product manager can work together with designer to create new layout or two architects can plan database schema and discuss required fields. In these scenarios real time discussion will be much better. Conclusion: use it when you want to work together, not to ask about very complex things, because probably it will require more time, more focus and some data gathering. 

Also remember that not all people can handle asynchronous communication in a good way: it is not only a skill issue, but our personality. I think asynchronous with more focus time is better for introverts, and more direct communication will be better for extraverts. The key is to find the golden mean: we work in teams, so not only our product is important, but also our relations inside the team. If we forget about that, then we will work only asynchronously: alone, and it will be not fun. 

Few words about FOMO effect

We live in busy times and often look for something to slow down, even if only a bit. Today I would like to raise the issue of FOMO: fear of miss out. Some people think it is a new phenomenon, but also limit it to only one activity. Last time I made some observations and had additional thoughts about that. Unfortunately, these thoughts are not optimistic: it looks like we have to face this a lot more often than we think. Fortunately, there are many options to handle this issue. 

Social Media

Most people think that the principal reason for the FOMO effect is social media. I think it is not true, but this effect is the most visible probably right there. It is because a lot of social media have been created (and are still developed) to bring our attention, our time. Such services are not free. We do not have to pay using dollars, we pay using our time and information about us we share with service providers. Many of our friends use the same social media like Facebook, Instagram, Snapchat or Twitter so it is very easy to check what they are doing, what they achieve etc. Most of these platforms also offer chat so everyone can send us messages quickly. As a result, the risk of the FOMO effect is very high: we are more and more dependent on the platform and we can think that everything is important, we should know about all these updates on feeds. Of course, it is not true.

Solution 

I will not write “just do not use social media, remove your Facebook account”. It is simple, but I think it is better to treat such platforms like a hammer – a tool for nailing, but nothing more. I like the marketplace; I use some groups (especially local communities) and follow local events. For that, social media can be helpful. On the other hand, I stopped following most of my “friends” – in quotes, because I do not often have contact with most of them. For me, it does not make any sense to know what they are doing. I also removed social media apps (including messenger, whatsapp etc.) from my phone and informed all important people: if there will be something urgent, call me. Do not write on chat and wait for a reply, because I do not know when I will read your message.

TV and news websites

You can find the FOMO effect also on TV and new websites. I live in Poland, and the war in the Ukraine was a “great example” of how it works. All media, all news websites informed about the course of the war, all the time. It was normal, Ukraine is very close, just abroad. We all followed this news and also wanted to help, but if we still and still and still watch TV or read news only to “keep all things in touch”… it does not make sense. We as individual people cannot stop the war, we cannot impact it in any way, but we can still feel that we should know about everything. Why?

Solution
Do watch TV and do not read news websites all the time. In reality, we should do this as little as possible, because most of the news is negative (to bring attention). For people addicted to news, it may be “brutal”, but the fact is we cannot do much. On the other hand, we can still live, care about our families and work. It is more important.  

Knowledge

What about personal development? The current world is a real rat’s race, but if we join it without thinking, we will be just stupid. I made a lot of mistakes and I think I wasted a lot of time. Example: I decided to learn Spanish and tried a few different ways, flashcards, music, writing something in this language etc. It was fine, it was something new but after time I still cannot say that I can speak Spanish. Why? Because I was learning without real usage, without practice. There was no opportunity or need to go to Spain. Of course, it was not totally wasted time, but I could have spent it in different ways and learned something closer, more necessary. Why did I do that? Because I felt that all people around me are doing something “for the future” and I also should do that.

Solution

Do not learn unnecessary things. Yes, I know, it is hard to say what is necessary and what is not necessary, but see this example: maybe you are a JavaScript developer. You can learn TypeScript and more JS to improve your current abilities, your current position, or you can spend the same time learning Java “by the way”, without a good plan. What will give you real benefits? If you want to change work and move to Java, then it is fine, but if there is only a small chance like “maybe in the future I will be a Java engineer”, then it does not make any sense. It is only an example, but fits to the overall knowledge. Life is too short to be a master of everything. 

Investing

We can observe the FOMO effect also while investing or saving. Last month we could observe high NTF and cryptocurrencies popularity. I am not a big fan of them, because in many places it is just a scam, like Tulip mania during Dutch Golden Age. I understand how it works, but I do not see real value, even if the US dollar also does not have real value right now (that’s true since the U.S. government broke away from the gold standard). Sometimes I feel that I make a mistake by not spending more time on NFTs and crypto… a lot of people I know do that and they often talk about these topics – it may be encouraging and skipping that may be a problem for a lot of us. I prefer a “more stable” investment option, even if it means lover revenues. 

Solution

Do not care about other people and what they are doing. You should create your investment plan and do not change it often. Changes means you are not stable. Also, just look at for example Forex stats: 95% of people lose most of their capital in a short period of time! Second thing: if you do not understand some aspects like NFT, do not try them. It is possible that even your neighbor invests in NFTs, but it is also possible that he does not understand them and real risk. Think about the risk you can accept and use only things in your “comfort zone”. Really, it is a better option for money you earned by hard work. 

Sport, hobby

More than a year ago I wrote that I removed my Strava account. After some time, I created it again… and then I removed it again. Right now, I do not use it and do not see any reasons to come back. For many people it is just a training tool – and it is fine. I do not need Strava, because I use my device sport platform, it provides me with more accurate and more helpful data. Other people want to observe friends or inspire based on different activities. We can use this example also on other hobbies. There is nothing wrong with inspiration from time to time, but what if we do something only because… other people do that? For me it does not make any sense and I decided to follow my own path – I have my goals, I want to try many different things, so I do not need external motivation. Also, comparing yourself to others does not make sense: it is always better to compare your current results with your previous results. Then you can talk about progress, changes etc.

Solution

If you have your goals in sport or other hobbies and follow different people, it is fine. If you build your goals based on different people’s activities then it is strange. Remember that you have only one life. It is not a game, you cannot save a game, try one option, then load and try different. If you will rely only on 

Work

After the pandemic a lot of us worked remotely. It is very comfortable and has a lot of advantages, but there are also downsides, similar to social media. We should rely on emails and also chat apps like Teams or Slack. Is it fine if we use them as help, but not as super important things? Most of the time, there are a lot of topics to discuss and there will be a lot of processes that are running without your participation. It may cause FOMO effect and additional stress.  

Solution

Work in async way as much as possible. You do not have to know about everything in your company, or even in your team. If someone sends you some questions, it will not ruin the world to send answers after a few hours, really. If possible, do not use work tools on your phone. Quick example: it is Friday evening; you want to rest but you will check your work email or chat… It is very possible that you will read about something important, and you will think about a solution, real rest will not be possible. Remember that it is not like working in a factory. You cannot bring machines from the factory to your home, but with office work, you will always carry your head, brain and all things inside with you. 

How to securely store JWT tokens

Last time I worked with some JWT tokens and had to resolve some issues related to security. Right now a lot of web applications and not only, because also mobile apps use these tokens to prove that we are valid and correctly logged-in users. The idea of JWT is clear, right and useful, but there are some dangerous traps during implementation on web applications. The main question is: where should we store JWT tokens to make them secure and still usable?

localStorage and sessionStorage are not good

On mobile clients, it is not a problem, because we can save them in some secure area. The thing is a bit complicated with web applications. If you already thought about this question and looked for some solutions, you probably found a lot of articles about that and some of them recommend using localStorage. During the latest years web developers got a lot of new abilities and localStorage is one of them: simple and very quick to use, it’s just something like:

// Write
localStorage.setItem('foo', 'bar')

// Read
cost myValue = localStorage.get('foo')

The big additional advantage: it is persistent storage, so even if the user closes the browser and opens again, it will still be logged in. Great! So, why not, why not use it just to store our JWT token? The problem with this approach is the possibility of stealing a token using an XSS attack. XSS is an injection and execution of malicious code on a user web browser. If there is any possibility that someone will do that on your web application, then it will be possible to just execute code to steal a JWT token – because it is accessible from JavaScript level. 

Of course, if we allow anyone to make an XSS attack, we have bigger problems… but think about that: in a big, complex web application, can you guarantee that there is no such possibility? We can not think in such a way and just assume that everything will be ok. The better approach is to think that everything will be bad. It is a reason why we do not have to use localStorage for JWT tokens or any sensitive data. 

What about sessionStorage? It is very similar: provides a quick, easy way to store some data, but it is not persistent as localStorage. If the user open a new tab or just close and reopen the browser, there will be no data we saved. It may be good for let say banking web applications, but for most others, it will be a very bad user experience. Also, sessionStorage is still vulnerable to XSS attacks. Maybe store them just in memory? It may be a solution, but you will have additional issues with persistence, and it will be very difficult to resolve. Conclusion: such storage are not a good option. 

Solution: use old school cookies

Yep, cookies come to rescue. Many people think that is old school, not used anymore. But in reality, they are still very good options in such cases. Why? First: they offer persistence. When we set cookies, we can also control expiration time. They are available in next tabs with the same web application, also after reloading and browser restart. Second: if configured correctly, they are not vulnerable for XSS attack. We can set the httpOnly flag on the cookie and after that it will not be visible from JavaScript level anymore. Wait a moment… you can ask: if it will not be available, how can we use a token from such a cookie in the authorization header?

The answer is: it will not be possible, but it is not a problem, because browsers will attach these cookies in each request and your API should just check cookies. In reality, cookies are also header, just different and process is automatic, browser will do that for you without any additional code. So, if the user has been authenticated and the API has set a proper cookie with JWT token, it will be automatically sent back, even in background (XHR, fetch) requests. So your frontend application does not have to handle that anymore.

Third: if configured correctly, it will be limited to only secure connections. Right now, all apps with public access should use secure, encrypted connections. Using a secure flag you can define that cookie should be used only on such connections, so if anyone will try to use your application on standard HTTP, such cookie will be not available and not used. Of course, you should still use different methods to provide HTTPS-only traffic: upgrade / rewrite and also send HSTS headers to inform browsers about rules for your websites. 

What about CSRF/XSRF issues?

We decided to move all things to cookies, our JWT token is not vulnerable to XSS attack, and we are happy… But just for a moment, because we remembered about different attack surfaces related to cookies: CSRF. Our API sets cookies and it looks fine, but an attacker can right now just prepare a special website and command our clients to send unauthorized requests in the background. Browsers will automatically add cookies in such requests as mentioned above, so it looks like the biggest advantage is also the biggest drawback. What can you do in such a situation? The first thing is to provide strict CSRF protection: send a special token from API to the browser, then attach this token to requests and validate on API: it guarantees that only the real client (i.e. our web application) makes all requests. The problem with that option is maybe we will need to change a lot of places in our code, also handling background requests will be not easy. 

Fortunately, there is a second solution, much simpler. We can add another flag to our cookies: sameSite. This option allows us to block sending cookies cross-site. Default option is “None” and it does not block anything, cross-site is possible (also with CSRF possibility). The second option is “Lax” – with such configuration browsers will not send cookies for images and frames, so it will prevent CSRF attacks. If the user clicks the URL to our website on a completely different website (or email), cookies will be added, so everything will work correctly. The latest option is “Strict”: in that case cross-site cookies are completely blocked, the most secure, but in some cases a bit limited option.

Conclusion

Use cookies to store JWT tokens – always secure, always httpOnly, and with the proper same site flag. This configuration will secure your client’s data, it will prevent XSS and CSRF attack and also should simplify web application, because you do not have to care about using tokens manually on frontend code anymore. 

Set-Cookie: jwt=OUR_TOKEN_CONTENT; secure; httpOnly; sameSite=Lax;

What about refresh tokens?

Exactly the same thing – they are also super important because they allow users to generate new JWT. If you use this token to determine: is a user logged in or not, you can stop doing that. Just save such information in localStorage (simple bool) if you need. It is not a problem: if the token expires, your API will inform the frontend about unauthorized requests, and then you can call the proper service to refresh the token. If the refresh token is expired or invalid, this service will inform you about that, so you will know that the user should be redirected to the login page. Yep, all these things without using tokens manually, it will be completely transparent from web application level.

Authorization service on different domain

Bonus case: what if our authorization service is on a completely different domain or subdomain? Let’s say we use oauth.mydomain to display and handle login pages, but our users will use different websites like app.mydomain. In this scenario, cookies will not work correctly, so what can we do? There are two options. First is to move login into the app subdomain or just the main domain (then cookies will be available on all subdomains – you can still control that) – may in many cases it may be not possible or just very, very complicated because we want to support many systems. Second option: just provide a proper URL on your app and use it like a “middleware” to call authorization service, so it will be Web App ⇔ API ⇔ Authorization Service. If oauth respond with correct data, you can set proper cookies for your current domain. 

Brownfield and Greenfield in software development

Software development is a complex project, especially if we work with something more complicated than just a simple CRUD application. If we want to cover a lot of business needs, we will have more and more requirements, new dilemmas, new use-cases and also a lot of things to monitor and check. Today I want to write about two project types: Greenfield and Brownfield. The fun fact is that nomenclature is from architectural business… and I work with software for architectural business, with AECO (Architecture, Engineering, Construction and Operation). Want to check? Visit Ingenious.BUILD on LinkedIn, we are hiring now. 

Ok, so what are the differences between them? Brownfield investment is an approach when we want to build something using existing terrains, existing buildings. We will have some existing problems to resolve, contaminations to remove or we will be removed by some law requirements related to the area we are interested in. Just imagine old buildings, maybe something like an abandoned former factory, big terrain you want to change to a new residential area. The Greenfield project is on the other hand something fresh. You have clean terrain and you can start everything from scratch, without checking anything from the past, no top-down restrictions, no complicated law processes.

The thing is similar in software development and software architecture, but with some important differences. According to what I wrote before, you can think that the greenfield project is always a better opportunity, and always gives us a better start. It is not true in the software world. Brownfield is like work with existing legacy code – and who does really like legacy, especially complicated legacy solutions? In this situation we have to rethink a lot of already existing parts of the system, we have to refactor some of them or just put them into the trash and write something again. It may be boring and it may be confusing for a lot of developers. The thing changes when we are at the point of contact between our code and our business requirements. Why?

The answer is simple: a brownfield project means we already have a lot of information. Yep, maybe we will need to adjust something, maybe remove or add something, but we already have a starting point, we already meet some business requirements and we can use that knowledge to improve our application. Just imagine building something like an Uber system from scratch and with something existing: there is a very very small chance that legacy code is completely useless: you can use it to determine requirements, check them and adjust. It’s even possible you will still use some of the parts, because they are good enough and will not require immediate refactoring. Also, if we already have some legacy solutions, we can easily add new members to our team, because we know what stack we use. It may not be super important at the start, but if we want to scale up, it will be more and more crucial for faster onboarding and verifying. Product part of our organization also has less to do, because we can reuse existing solutions. 

On the greenfield project the situation is only seemingly simpler. Of course we can start from scratch, but in most cases, we will have many more questions than answers: what are our real requirements? What business problems do we want to solve? What stack should we use for that? If everything is clear, we have all the information, then yep, it will be a piece of cake. But it’s a utopian assumption: we will not have all the information and business will verify our plans after first usage. That is why quick implementation – even if our application is not perfect, not ready for all cases – is so important: we will have feedback and it will be possible to make all required adjustments. And guess what… your greenfield project becomes a brownfield project then – you will avoid it only in very simple cases. 

Architecture Decision Record (ADR)

During software developing we often have some questions, especially when we join existing projects: why app uses that language? Why these solutions? Why we handle time or money values in such way? All these questions are very important, because it is a part of application architecture. Of course we can on team knowledge, but such method is not efficient and not possible to maintain on larger projects and when we want to scale up: new people will join, but some people will also leave project. Important knowledge distributed partially to different people will be hard to get. The solution is ADR: Architecture Decision Record.

Architecture Decision Record is just a document with information about why and when team decided to use some solutions. It can describe additional context and consequences of adopting the decision. In effect, we have one, central place with all required knowledge, with history and detailed descriptions. It helps during onboarding new people, because they can check ADRs quickly. It helps if we lost some project members, because we will not lost important knowledge. It also helps if we make changes on some modules ownership, introduce internal structure changes, because we still everything important in one place. Finally, it allows us to such documents in code, explain why we make adjustments – everything is clear then.

When should we create ADR?

As soon as possible. It is long-term solution – we will not see positive effect immediately, but after some time, it will help us. More detailed question: should we create it only for bigger things, or also smaller? It is flexible. We definitely should describe bigger decisions, in smaller it depends how they will impact our application. We can start to write ADR when we have a problem, even if we do not have any solution for that problem: it allows us to aggregate potential options, then discuss and finally decide and approve the best approach. In such case, we will have clear history what prompted us to make this decision.

ADR example

There are many different patterns of creating ADR and there is no right answer for question “which one should I use”. It depends on your needs, application structure,

NUMBER – ADR NAME

Status

(…)

Date

(…)

Context

(…)

Decision

(…)

Consequences

(…)

And real example:

1. Use standard HTTP response codes

Status

Approved

Date

26/02/2022

Context

There are many possible options to send responses – even if action will fail (for example we cant find model), it is still possible to send completely different response code (example: 200 OK). We should avoid that and make all responses clear, predictable and easy to interpret: we can use our rules, or follow global HTTP recommendations.

Decision

We decided that we will always use only valid, recommended HTTP response codes, for example 403 if access is forbidden, 404 if we will not able to find model etc.

Consequences

– All new endpoints will return only valid codes

– We will not accept custom or invalid response codes on code reviews and merge requests

– Legacy endpoints will be updated during required refactors

Where should we store ADRs?

Similar to how should ADR look like, there is no simple answer, but there is the same rule: you should define one place and use it for all ADRs. You can store them on repository and make close to code, you can use shareable notes, cloud with just txt files or anything else. The important part here is: you should backup your ADRs (or service you will use should offer that) and also, it should be possible to share ADRs for read-only. It’s required if you want to link to them in code comments, tasks descriptions or other architecture considerations.