Hi, and welcome! My name is Igor Sarcevic. I'm a software engineer, amateur adventurer, math enthusiasts. This is my personal blog where I write about technology, philosophy, and share my insights about the human condition.
Killing processes in a Unix-like system can be trickier than expected. Last week I was debugging an odd issue related to job stopping on Semaphore. More specifically, an issue related to the killing of a running process in a job.
We made some major steps in software automation, more specifically release automation. We coined the word DevOps and invented a culture that unites developers and operations. We invented the term infrastructure as code that represents our...
Mentoring younger developers is a very rewarding experience. It challenges your your pre-established ways of thinking, and it forces you to re-evaluate your long held principles. For example, a simple question like “Why does it matter to...
Last week I was debugging a weird bug in one of our services. In the logs we saw an SQL error “repetition-operator operand invalid”, so I was pretty sure that we have a broken SQL comparison in one of our services. The weird part was that this error happened only occasionally, seemingly randomly.
A year ago, I made a big decision — I decided to start working from home. This decision had a significant impact on my personal and professional life. It changed the way I approach people. It changed the way how I plan out my day. Most importantly...
Last week we’ve investigated a way to achieve stable pagination for our new API. I’ve learned some new techniques for handling pagination, and dig deep into the downsides of standard — offset based — pagination.
Recently I switched my ISP provider and with the change I’ve got a new WiFi router. The download speed is incredible, 10x the compared to my previous subscription, but the stability got worse.
As a software engineer, I know my way around...
Slow database queries harm your organization in many ways. They can damage the reputation of otherwise great applications, make background processing painfully slow, and drastically increase the cost of your infrastructure. As a seasoned web developer, it is absolutely essential to learn about optimization strategies for your data layer.
In concurrent systems where resources are locked, two or more processes can end up in a state in which each process is waiting for the other one. This state is called a deadlock. Deadlocks are an important issues that can happen in any database and can be scary when you encounter them for the first time.
The most prominent feature of PostgreSQL is how it handles concurrency. Reads never block writes, and writes never block reads. To achieve this, PostgreSQL uses the Multi Version Concurrency Control (MVCC) model, an elegant solution for a very hard problem. If you want to design highly concurrent applications, you should really invest the time to understand the bits and bolts of this mechanism.
Misunderstanding transaction isolation levels can lead to disgusting side effects in your application. Debugging such issues can be more than painful. The SQL standard defines four levels of transaction isolation. Each of these isolation levels defines what happens if two concurrent processes try to read data updated by other processes.
A regular select statement does not give you enough protection if you want to query data and make a change in the database related to it. Other transactions can update or delete the data you just queried. PostgreSQL offers additional select statements that lock on read and provide an extra layer of safety.
PostgreSQL provides the means for creating locks with application defined meaning. These locks are called Advisory Locks and are an ideal candidate for concurrency control where the standard MVCC (multiversion concurrency control) doesn’t fit the bill. Advisory Locks can be the perfect tool in your arsenal when you need to control access to a shared resource in a distributed system.
Locking is an important topic in any kind of database. Without properly handling locks, an application might not only be slow, it might also be wrong and behave in some insane ways. Therefore, learning proper locking techniques is essential for good performance and correctness of our applications.
I have learned an important lesson this year. A clear separation between queries and commands can bring a lot of long term benefits to your code.
Being more productive was always a topic that interested me. Small life hacks here and there can definitely add up.
Your monolith was slowing you down, and you have decided that it is time to invest in a multiple service based approach. There were lot of new things to learn, but finally, you are free to experiment with new technologies. Your services can be developed & deployed independently. Life is good.
Your project and organization are getting bigger, and you start to notice that your monolith is getting out of hand. Trying out new technologies is out of question. You are stuck with the same language and platform from 5 years ago. Microservices are here to save the day! You decide to expose an internal API, and limit development of new features exclusively as microservices.
If you are a bit like me, you are naturally quite neurotic and experience feelings such as anxiety, worry, fear, anger and frustration more often than you should. Deep down, your rational self knows that these feelings should not control your life. However, detaching from the ‘now’, zooming out and focusing on the big picture is easier said than done.
I’ve used Linux as my primary operating system for well over ten years, yet I still stumble upon things that are completely unknown to me. For example, several days ago, I wanted to display a formated table in my terminal.
When I started writing articles for this blog, I only needed to open a text editor, write something interesting and publish it. This in itself was already hard enough. Expressing your own thoughts and feelings to the world is frightening, yet the practice is very rewarding and eyeopening at the same time.
My Rails app used to be fast and snappy, and everything was working just fine for several months. Then, slowly, as my product grew and users started to flock in, web requests become slow and my database’s CPU usage started hitting the roof...
Ruby and Rails are slow — this argument is often used to downplay the worth of the language and the framework. This statement in itself is not false. Generally speaking, Ruby is slower than its direct competitors such as Node.js and Python...
After weeks of planing, painful debugging sessions, and making sure that everything is covered with tests, your feature branch turns green. You are ready to merge into master and deploy to production. You hit the “Merge” button on GitHub, open your CI service and watch how master turns green. Automatically, deployment to production is triggered, and after several minutes your new feature goes live.
Ruby is not the fastest language, nor is it the simplest language, but damn it, it is definitely one of the most fun languages out there. For someone like me, who enjoys programming maybe a bit too much, a language that puts little or no limitations on the things I can tweak feels very natural and an obvious choice when it comes to solving complex issues.
32 Better Sleep
Every three months, I like to sit down, zoom out from daily issues, and focus on the big picture. I like to write down the things I want to achieve, and to find out what is really important to me. This three month schedule is ideal, as it is not too long so that I lose focus, nor is it too short for it to feel daunting and boring.
A good craftsman is known by his tools. He never uses the biggest hammer in his shed to fix a little bump, neither does he use a duct tape to join together the most fragile parts of his craft. For a good craftsman both a hammer and a duct tape are vital elements of his toolbox. He has a good eye, and the intuition to choose the most appropriate tool for every situation he faces.
Deploying your services packaged in lightweight Docker images has many practical benefits. In a container, your service usually comes with all the dependencies it needs to run, it’s isolated from the rest of the system, and deployment is...
This year I made a concious effort to improve many things in my life. I have started to exercise regularly, improved my diet drastically, started to write a journal, and to retrospect my life and goals on a regular basis. One of changes that I am most proud of is my changed attitude toward books.
A lot of developers choose to avoid the often big, clumsy and complicated IDEs in favor of the Linux command line. At first sight the command line is inferior to the experience you get from a full blown IDE. However, the beauty of the command line is just that. It is fast, simple, and by default it comes with very small set of pre-installed features.
Over the last fifteen years, SSH has become a standard tool for remote management of Unix-like systems and many network devices. SSH stands for Secure Shell, and is one of the ways to get a command line (shell) access on a remote machine...
Rails is great, but often it is not the best tool for creating smaller applications. For smaller size apps, especially those that are mainly focused around pure JSON APIs, Sinatra is often a far better option. Unfortunately, the majority...
Mocha is a testing library for Node.js, created to be a simple, extensible, and fast testing suite. It’s used for unit and integration testing, and it’s a great candidate for BDD (Behavior Driven Development).
This is how usually all our geeky adventures start out: A colleague walks up to my desk
and says: “I must show you something interesting!!!”. Last Friday this cool thing was
Several days ago a colleague and I wanted to check whether our caching system contains all the files that we expect it to contain. We started by writing a bash command that would list and compare the available files. It had the following structure:
Let’s say you have two servers named
charmander, and a configuration
config.xml that should be present on each server. Due to some human error
the files got different and your servers started to act weird. It would be nice
to compare them and find out what part of them is different.
Did you ever had to rename a part of a relly long filename?
We, software developers, like to call ourselves computer scientist, software engineers or data scientists. Hah, what a load of bulls*it!
I remember the first time I tried to use the shell. It was weird that I had to type in things and not just click around to get things done. But gradually I got used to it, and after a while it became my primary way to interact with my computer.
Many developers fail to realize that by using the basic Unix tools, you can find on any server, you can find and collect valuable data from your logs. Often the data you need can be found without using any external services, including but not limited to service measurements.
Last time, I have demonstrated how we can put together simple filters to show only the lines we are interested in. This time I will show you how you can manipulate these lines and select only the parts you really need.
Many developers fail to realize that using the basic Unix tools, you can find on any server, you can find and collect valuable data from your logs. Often the data you need can be found without using any external services, including but not limited to service measurements.
Ruby is an excellent language offering us a simple and human friendly interface, however for system administration or simple task automation the shell is a much better alternative. Luckily, combining them is easy.
The majority of today’s development is oriented around the web or around desktop/mobile applications. For the average programmer it could even seem like there is no other programming area out there. However, there is actually a huge number of programs developed for cars, televisions, phones, and similar everyday technologies. This article is focused on a small fraction of those areas — sms messages.
I have been programming for a long time. Probably much longer than I want to admit. Yet, for a long time, there was something mysterious about the way I created my programs. Yes, I could write a lot of stuff in programming languages, but I had no idea how to create a programming language itself.
Not so long ago, while reading an article on hacker news, I came across a strange little programming puzzle that seemed silly and trivial. I was sure I could solve it in a matter of minutes if I just sit down and think about it a little. Yet, the problem haunted me for weeks, and in one moment I just had to sit down and solve it. And what can I say, it was really hard, way harder than I tough. Here are the rules of the challenge.
Unix systems are really smart when it comes to interpreting your application. Not only do they provide you with an excellent environment for development, but also let you specify the interpreter in you source file. As it turns out, this technique lets you write an application in any programming language without forcing your end users to know the details of your implementation. This article is about describing this simple technique.
Two years ago I thought I knew a lot about the Linux command line. Then I started digging deeper. Replaced Bash with Zsh, learned about jobs, started writing shell scripts, and even ditched Sublime text in favor of editing with command line Vim. Again I thought I know a lot about the Linux command line. Then I started digging deeper again…
Have you ever wanted to create an awesome command line application but was lost in the sea of options parsing? Well, if you did, and even if you didn’t, Thor is here to help you.
There are times when the only thing I want to create is a simple API. In the Ruby ecosystem the standard for creating something simple is Sinatra. But, there are a lot of things you miss in Sinatra that you have predefined in Rails. Sinatra let’s you define and include only the things you actually need. Maybe this is a good thing, maybe it is not.
Downloading a file, backing up your database, or installing a package for your system are all instances of long lived processes that we encounter daily. When such a process takes a long time to finish, it is always nice to give some kind of visual cue to the user.
In programming we like to reuse stuff. Data, variables, classes and even whole systems. We have a rule of thumb to only write code if it can not be found somewhere else. But sometimes the same thing can have a different meaning in a different context. So in order to reuse code but have a meaningful name in various contexts, we use aliases.
Here is a story of my typical work session in the shell. It starts by a wish to make the computer execute some of my commands. For example, I want to list all the files in the current directory. From prior knowledge I know that the
ls command does exactly that, so I use it, and get the desired output. But I am out of luck, the current directory contains too many entries and I just can’t scroll so much up in the history.