About me

Want to know a bit more about me? Perhaps you'd like to hear about my opinions as a developer? Or maybe to get a full overview of the tech stacks that I have used in the past? Perhaps you just care to learn more about who I am as a person? If that's the case, you should find it all on this page!

My technology stack(s)

My CV contains just a quick overview of some of the more popular technologies that I've used in the past. That said, I don't necessarily believe that just a list of names expresses all that much about the countless experiences that someone has had with a particular tool or technology. Because of this, I've decided to not just list the technologies that I've used, but to also introduce a bit of context, so you can find out more about my journey into software development.

You can click on any of the items below to expand them, to read more about my experience. I don't actually expect anyone to read all of it, but if you get curious about my experience with a particular technology, then feel free to have a look (I also expand the first one by default, to aid with the discoverability a bit, in case you don't read this).

Back end

This is where some of my best strengths lie. There are many things to take into account while developing the back end application and APIs of an application and I've had plenty of experience with this! While some people specialize in just one or two technologies, I've also had the pleasure of working with most of the more popular options out there. Furthermore, I'm a self-starter and therefore have successfully bootstrapped many projects and have seen them through to completion.

  • code Java (Spring, Spring Boot, JPA (Hibernate), myBatis, PrimeFaces, sometimes Quarkus/Dropwizard, JUnit)

    Java is actually one of the first languages that I learnt (after BASIC and Pascal) and has essentially been a reliable workhorse ever since. I've found, that Java strikes a good balance between the speed of development and its runtime performance. In addition, the ecosystem surrounding it provides a variety of good libraries and frameworks for most situations.

    Personally, however, I do believe that packaging .war files and administering instances of Tomcat/TomEE/GlassFish separately is a waste of time in comparison to fat .jar files with Spring Boot or similar frameworks. The latter approach is far superior in regards to managing dependencies and that makes the eventual migration to containers really easy.

  • code .NET (especially .NET Core, ASP.NET Core, EF Core)

    I have used .NET for the occasional project here and there, which has lead me to believe that the CLR technology and the C# language should be more widely adopted! Not only is the performance and functionality lovely, but ever since the release of .NET Core it's finally been properly cross platform, especially with Kestrel! In addition, in my opinion their approach to LINQ was way better than that of Java Streams and frameworks like EF core are better integrated than JPA with Hibernate or other providers.

    A sad trend I've noticed is the fact that many companies still bother with running older .NET versions in Windows deployments, which is sub optimal, given the progress that has been made in the newer versions.

  • code Node (Express.js and a variety of libraries)

    Personally, I rather dislike ECMAScript and its many idiosyncrasies, as well as the lack of proper threading (at least in a browser context even service workers feel poorly tacked on).

    However, there is definitely something to be said about the idea of being able to write your front end and back end code in the same language, for which the Node.js platform is indeed a good fit! It has the potential to noticeably increase the speed at which you can develop solutions, as well as frameworks like Express.js can make web development pretty simple, due to its approach to introducing middleware logic.

  • code Python (Django or Flask, but mostly for scripts)

    In my experience, Python has been a surprisingly readable and sane language, with an exceptionally strong ecosystem for working in most domains, be it image processing, number crunching, or even web development. I actually have some projects with Flask (and some smaller stuff with Django) under my belt, as well as CLI apps, motion detection scripts, as well as infrastructure automation tools!

    Python is definitely competent when it comes to web development, however personally I'd avoid it for most projects that need good runtime performance, unless you're under a lot of pressure to develop things quickly or are able to avoid a lot of hardware to run your app.

  • code PHP (Laravel, Lumen and pure PHP)

    Many people dislike PHP for it being a fractal of bad design, however it's hard to argue against how good it is when you need to prototype something quickly. In addition, it is one of the easiest ways to get static rendering in your projects, rivaling the ease of use of CGI of the olden days. Were the standard library better, I'd personally use it more often! Of course, one of the very valid criticisms that I agree with, is that it's easy to do PHP wrong as well.

    There are many bad codebases out there, for example, Wordpress, which I'd prefer to avoid.

  • code Ruby (Ruby on Rails)

    In short, Ruby is a better PHP and Rails is a lovely and widely used framework, which is very well suited to the most web app development needs and excels at server side rendering. It doesn't pretend that it should be suited for all of the general computing tasks, which isn't necessarily a bad thing either!

    My only personal nitpicks would be about its performance, which make it not the best choice sometimes as well as the fact that in my opinion "convention over configuration" is almost always a bad idea and hurts discoverability. Thankfully, the documentation is good and there are ample tutorials available!

    Well, there's also the fact that you're looking at a site made in Ruby on Rails right now, so even though what i said in regards to performance and its other drawbacks is still true in my eyes, it was pretty well suited for the needs of this site!

  • code Go (some small exploratory projects)

    A few years ago, Google came out with a new language that was statically compiled like Java, with the exception that there'd be no need for anything to interpret bytecode - it'd run natively on the user's platform of choice. Due to this similarity to my childhood darling, Pascal (a language that's painfully underrated, especially for its RAD capabilities), I decided to check it out in a few small microservices projects.

    Personally, my impression was that it's pretty good, even if the ecosystem itself surrounding the language isn't entirely mature yet. That said, it seems like the language itself has been pretty successful in a variety of tooling related projects as well!

  • code Other languages (just a few additional tidbits)

    In addition to the above (which I'd like to use in commercial projects), I've also had the pleasure (or, in some cases, displeasure) of exploring other languages as well.

    Sometimes, they had wildly different paradigms, like Prolog for logical programming. Other times, they were really low level (like ASM), super specific (WSDL, XSD) or simply dated (VB.NET, VBA, VB6). Other times, the languages themselves seemed to be good, but I got the vibes that I wouldn't like to use them in my everyday work (C, C++, Lua).

    Of course, there have also been some that I've been curious about, but simply haven't explored them yet, because the above take care of my needs for the most part - notably Rust and most of the "true" functional languages, like Lisp and Haskell. Maybe some day I'll at least find the time to explore Scala/Clojure or F# at least, since I'm already familiar with JVM/CLR. Or maybe I'll play around with Kotlin in more detail.

  • check_box Testing (this deserves a separate paragraph)

    Testing is a difficult topic to cover. I've worked with both systems which need a high test coverage, as well as those that are inherently difficult to test.

    In that regard, I've found that there are two types of systems. For the first type, the suggestion of "Write tests. Not too many. Mostly integration." must be remembered, especially when faced with limited time and other resources. There are plenty of systems out there which don't lend themselves well for more granular testing, but for which testing functional blocks is a very efficient approach. For the second type, which in my experience is considerably more rare, the functionality is loosely coupled enough to be extensively testable. For these systems, approaches like TDD make sense. Not only that, but refactoring can also be done with far more confidence. I hope to work with more systems of this kind.

    Regardless, I do believe that testing matters, even if it sometimes forces you to structure your code in particular ways or make certain architectural choices. I've worked with testing automation, be it setting them up to execute as a part of CI processes or alongside merge requests, or maybe working with Selenium to automate browser testing. The biggest game changer that I've seen is also setting the pipelines up in such a way that DB migrations can also be tested against a temporary DB container.

    In addition, performance tests also shouldn't be forgotten about, which is why I've successfully used K3s and similar solutions in the past for load testing. I actually wrote a real world performance benchmark platform as a part of my Bachelor's degree thesis way back, to compare how performant Java and .NET Core were in comparison to one another in real world circumstances.

  • security Security engineering (something that should always be on your mind)

    Personally, I find that making secure solutions oftentimes slows down development significantly, much like having an all encompassing suite of tests also does - however, it's often a worthwhile investment. It's definitely something that should be given plenty of attention throughout the development process - be it in a zero trust environment, or even one that you control yourself. Defense in depth should be prioritized over having a perimeter as your only defense.

    I've had plenty of experience with hardening GNU/Linux servers to a reasonable degree, ensuring that web applications use SSL/TLS and that the certificate renewal is properly taken care of, be it when using a personal CA, or something like certbot/Let's Encrypt. Not only that, but oftentimes it's good to have the communication between your internal APIs also be encrypted, be it with the help of a service mesh, like Consul, or by using something like Docker Swarm with overlay networking. Of course, that's not enough, so I've also worked with a variety of authentication and authorization methods, everything from integrating with OAuth2, setting up two way SSL with client certificates, implementing RBAC, doing access token based setups in time constrained scenarios, all the way to thinking about how to hash and salt passwords and store them.

    Caring about the security of your entire system can take a lot of effort, however it's a must when you're working with finance data or anything else of value. Furthermore, there is no single easy solution for all of your problems - you need to protect yourself against everything from social engineering, phishing etc. It doesn't matter if your system is secure if your password has been leaked or can be brute forced (though fail2ban might have a thing or two to say there). Also, you should probably invest at least some resources into automated scanning solutions, both for your code, as well as your infrastructure (for example, OpenVAS).

    Overall, I'd also like to mention this presentation here, which i found very useful: Secure by Design - Security Principles for the Working Architect - Eoin Woods.

  • timer Performance optimization (your systems will need to scale sooner or later)

    In my eyes, performance is important. It should be thought about from the first day of development, so that the correct choices can be made to avoid large problems down the road. Sure, at the same time it should never compromise your ability to deliver on features. Accruing a little bit of technical debt and not squeezing every CPU cycle out of your servers is okay as long as you get things done at the end of the day, otherwise no one would use Python or Ruby.

    Yet, I've found that being able to figure out where bottlenecks lie in systems and which parts could be optimized for the most gains in performance is a useful skill to have. And it doesn't even matter, whether we're talking about the system architecture, whether it scales vertically or horizontally, how it deals with backpressure, or details of the underlying platform, be it a GC implementation, or whether a web server processes requests in a blocking manner - all of those matter.

    If i got a Euro for every time when someone's N+1 ORM DB queries make an app unusably slow when there's suddenly more data in the system... well, I'd have a lot of Euros. Same thing for the times I've seen badly implemented caching and cache invalidation cause data consistency issues. Then again, those experiences have only encouraged me to think more about how to write performant code, consider the drawbacks and suggest to others to do the same.

  • forum Integrating systems (a bit about APIs)

    I've also had a decent amount of experience making all sorts of distributed systems work together, in a variety of protocols and methods.

    Everything from JSON APIs, RESTful APIs (the proper kind, as explained by Dylan Beattie), to even older technologies like SOAP. Speaking of SOAP, despite the cumbersome implementation, I actually found the idea of WSDL and the concept of being able to generate client code and stubs from a service description file to be brilliant! It's a shame that WADL never took off, though thankfully Swagger and OpenAPI slowly fill in that gap.

    Furthermore, my experience with implementing event based systems has also been mostly positive and I rather enjoy the idea of applying CQRS in practice! On that same note, messaging and queueing systems like RabbitMQ are lovely to deal with backpressure and load spikes!

    I'm also eager to become more accustomed with gRPC and things like GraphQL as I'd like, yet those are a bit niche. Oh, and I've also used WebSockets for near real time communication (in an auction system)!

  • computer Other types of software (I've done a bit more than just webdev)

    This page is primarily meant to list some of the technologies I've utilized for web development, but that's not nearly all that I've done in the past!

    As a matter of fact, I've also used both C# (with Unity) and Java (with jMonkeyEngine) for the development of interactive visualizations and video games for a variety of desktop and mobile platforms.

    Furthermore, in my experience both Swing for Java and WinForms/WPF for .NET are good approaches for the development of GUI software (though the latter is not cross platform). In regards to desktop software, this is also where I think Pascal shines with the Lazarus IDE and LCL libraries. Of course, if you don't care about native application, then something like Electron could also work, with a few pitfalls.

    Oh, and I've done some basic work with creating Android apps as well, though platforms like Xamarin could be useful for easily approachable mobile cross platform apps as well, in addition to web based tech, like React Native.

Front end

In the past decade, front end development has become a worthy craft in of itself, in part due to the fact that there are far more devices and browsers to support, but also because the toolchains and frameworks have become both more advanced and complex. Luckily, I'm also a pretty competent front end developer, as a part of working on the full stack - seeing as it's never enough to just write the back end or develop the database, but rather the whole solution needs to come together and be integrated well.

  • code JavaScript and TypeScript (the only popular languages for front end development)

    Some people lean more into the direction of one or the other, but personally I think that each has their merits and I've used both to pretty good success.

    In my opinion, JavaScript will almost always be easier to deal with and quicker to use, even if it has plenty of odd bits about it, which can eventually become stumbling blocks of sorts. On the other hand, TypeScript is good for when you want to make sure that your code doesn't do oddities and get that little bit of help that you'd get while doing most back end development with statically compiled languages.

    That said, I believe that it's absolutely essential to check how good TypeScript integrates with your frameworks of choice. For example, since the new versions of Angular were built for TypeScript in particular, the integration there is smooth, the documentation is good and overall it's an extremely pleasant experience. Yet, in regards to React and Vue, that hasn't been my experience with TypeScript at all. So, consider your options before making that choice.

  • code React (with JS/TS, libraries like Reactstrap etc.)

    This is one of my favourite libraries for creating front end application and single page application! The idea of using a specialized syntax like JSX and putting in the effort to ensure data binding out the box has been a wildly successful in my opinion. In combination with component libraries, I find React to hit the sweet spot for developing things quickly and easily.

    However, there are also some things that I don't necessarily enjoy. For starters, I much prefer the class based component model to using hooks - I've done both, yet the class based approach seems far more structured. Also, while I support the idea of having a single source of truth, introducing Redux into projects can make them need unwieldy amounts of boilerplate code just to keep the state up to date. Personally, I'd either consider using the Context API, or would use an alternative solution like MobX.

    Lastly, there's nothing that kills the development velocity in React projects like using TypeScript. There are good integrations of TypeScript into front end technologies (see Angular below), but React is not one of them, since a lot of uncomfortable structures quickly appear.

  • code Angular (with TS, libraries like ngBootstrap etc.)

    Whereas React projects usually are a lot of integrated libraries that work together (for the most part), the approach of Angular is somewhat different, since it attempts to provide a large amount of tightly integrated pieces of functionality that covers a lot of use cases.

    That's why some say that it's difficult to compare a library against a framework, but personally I imagine to be a bit like GNU/Linux vs FreeBSD, those having a slightly different design philosophy. Admittedly, however, even though Angular has a lot of good stuff under the hood, I've found that its adoption isn't as high as that of React. Yet, it is still a capable option for all sorts of projects, even if the bundle sizes would be slightly bigger than those of React.

  • code Vue (with JS, libraries like BootstrapVue etc.)

    It's a bit surprising, how quickly Vue's popularity has risen. In my experience, it's a good alternative to React, that's a bit closer to pure JS, rather than all of the fancy JSX syntax. It's also well known for smaller bundle sizes than either of the above and good runtime performance. I've used it for a real time auction system in the past and the experience was fairly good!

    In my opinion, Vue is a strong contender for most projects, without too many thorns or oddities!

  • code jQuery (really only useful in legacy projects)

    It's undeniable that jQuery has a piece in the history of front end development libraries and even nowadays it's not too hard to stumble upon it in the wild. That said, the alternatives above seem superior to it in many ways.

    In the current year, I would only reach for jQuery, if I needed to introduce very sparse bits of interactivity to a web page, whilst at the same time not wanting to deal with Vanilla JS. Sadly, there are many external libraries and application which still require jQuery just to function. Its downfall is the fact that occasionally you might run into functionality that requires a particular version of it and I've actually seen sites that load more than just 1 version of it, leading to a lot of bloat in regards to the page size. Lastly, code splitting is almost non-existant for it.

  • code Angular.js (a thorn in maintenance projects)

    Angular.js is something that I've encountered in legacy projects and working with it has been a disappointing experience.

    On one hand, it's nice that it eventually lead to the newer versions of Angular, however for those stuck with the older version, there's a lot of strife. From unclear ways of binding component attributes, limited two way data binding capabilities, brittle directives and a variety of other problems, I've seem it affect projects in some unfortunate ways. For example, in one project introducing new application was so cumbersome, that instead of bothering with it, instead the application state was stored in a few huge objects, which got passed around and were mutated. Not only that, but the few application that were present, covered entire pages and were thousands of lines long.

  • brush CSS frameworks and libraries (Bootstrap, Bulma, Materialize and others)

    CSS frameworks and libraries also deserve a mention, if we're talking about front end development. After all, how our pages look is important, because it'll affect the user experience and may make or break the acquisition of a new user!

    A lot of my experience lies in utilizing standard frameworks to great effect - relying on the likes of Bootstrap, Bulma, Materialize, Pure.css, Skeleton or others hasn't failed me so far! Even this site makes liberal use of Materialize. Much of the appeal is in finding a consistent set of components and styles to use and then to build upon those, introducing all of the additional styling and components that the project needs.

    Of course, when there is the need for something more bespoke, I've also used lower level frameworks like Tailwind CSS, though I believe that you need to be careful with those, due to the potential complexity that they might introduce. Furthermore, it's also important to consider what the size of any individual framework may be, because large download sizes are not always worth it, no matter what your site ends up looking like.

  • dns Server side rendering (depending on the back end tech)

    What do you do, when you don't want to have a separate front end framework or a mix of libraries? What about when you don't want to deal with the technical complexity, nor the performance overhead?

    It's simple - you use server side rendering! Well, admittedly you can do that with most of the frameworks above as well, however there are plenty of wonderfully simple templating solutions out there for the more static sites. Personally, I think that it's more in line with how the web should have been - a collection of interlinked documents, because of which I rather enjoy using server side rendering in a variety of scenarios.

    I've used JSP, JSP and PrimeFaces with Java, I've done static rendering in PHP and Ruby (which is precisely what you're looking at right now), as well as have used hydration for some React sites that would allow basic functionality even with disabled JS

  • accessibility SEO, accessibility and performance optimization (something to pay attention to)

    I rather enjoy optimizing my code, both in regards to back end and front end application. Therefore, I'm actually pretty happy that nowadays sites having good performance characteristics is a must, given how competitive the web can be! Of course, sometimes these optimizations can get a bit nitpicky (modern image formats with low adoption, anyone?), but in my experience it's definitely worth it! For example, just have a look at Google PageSpeed Insights for this page which should give you an idea of what can be achieved with a bit of care.

    In addition, not only do I believe that simpler and static sites are oftentimes excellent in regards to usability, but I also think that care should be given to make sites accessible to those, who are differently abled. Screen reader support, text readability, element placement and other UX concerns should all trump flashy design most of the time! Lastly, I think it's a good idea to work on SEO - not just because of some arbitrary decisions made by those who govern over search engines, but also because having canonical and human readable links is a good idea. In my eyes, it should be user friendly, be it because of clear page titles, descriptions, tags, or even using standards like OpenGraph for allowing easier previews and page categorization.

  • signal_wifi_off PWAs (sometimes useful to have)

    I also have some experience with progressive web apps, which in my experience are a good idea to enhance mobile users' experience a little bit more than just a website would allow. That said, in many cases there still will be certain drawbacks to that approach and the codebase could get needlessly bloated.

    Personally, I don't think that a blog should necessarily be a PWA, however an application definitely could! Of course, that also brings up the discussion of whether it's useful or just a gimmick, when creating a hybrid mobile application isn't too difficult nowadays either, the application strength that I can think of being not needing to integrate with any particular app store.

DevOps

I've also taken a healthy interest in both getting things up and running, as well as keeping them this way, because of which I have a good amount of DevOps experience! I've seen many projects where people don't think about site reliability engineering and personally, I believe that DevOps is a bit part of achieving good uptime and reliability! To this end, I've studied a variety of technologies and approaches, everything from your typical GNU/Linux distributions and scripting for servers, to containerization, configuration management, load balancing and others.

  • dns GNU/Linux (Debian, Ubuntu, CentOS, RHEL)

    In addition to developing apps, I've also taken a healthy interest in the ways to get them deployed - thus, I've had a decent amount of experience with setting up and administering various installations of GNU/Linux distributions. Now, there has been the occasional foray with non-GNU distributions (like Alpine Linux, which is an excellent solution for container base images), as well as working with Windows Server, yet I've found the latter to be inferior for fulfilling the server role.

    Actually, even now I run my own hybrid cloud and a homelab, in which I explore a variety of new technologies and also host this very site that you're looking at, in addition to the necessary infrastructure for backups, monitoring, load balancing, CI/CD, code analysis, security scanning etc. If you're interested in that, you can read more about it on my blog.

  • code Shell scripting (Bash, PowerShell)

    With the above, also comes the necessity to create a variety of shell scripts, be it for automating cumbersome processes, minimizing the risks caused by the human factor, or even avoiding the need to create cumbersome executables for accomplishing small tasks. While most of the above can indeed be accomplished with either Bourne shell (sh), Bourne again shell (Bash) or most other shells, in my experience I've found them to be cumbersome and not user friendly, the ease of execution being their only boon, as well as being able to interface with the GNU tools. While I've written plenty of shell scripts and see the value in them, at the same time I'd also consider more specialized tools.

    In my mind, the ideal shell would be more like Python, with simple semantics and excellent readability, yet it'll also almost never be possible to rely on any of them due to how rare it is to see ksh, zsh or even the Oil shell. On a more positive note, I actually found myself really liking the ideas behind PowerShell - parsing text only goes so far and working with objects has a lot of benefits! That said, PowerShell is also primarily constrained to Windows environments.

  • build Configuration automation (Ansible and GitOps)

    Administering servers manually only goes so far - sadly, the overwhelming majority of the deployments that I've seen have been managed that way. Even if there are no immediately apparent problems with that, there is definitely something to be said about how discoverability, observability and configuration management could be improved. One doesn't have to look at horror stories like those of Knight Capital but rather it should be sufficient just to ask yourselves how someone will be able to administer a server without talking to the person who set it up. Alternatively, how will you set up an entirely new environment, or see who has done those changes?

    Here, tools like Ansible excel and I've had the pleasure of introducing it to most of the environments, even if just to set up tools, user accounts, directory structures, firewall rules and bootstrap container clusters for containerized developments. In my experience it works so good in combination with the GitOps approach, in which the configuration is also versioned, that it's possible to deny regular users write permissions on the servers entirely. Furthermore, my method of testing whether these deployments were good enough, was to just wipe the application directory from the server entirely (or to reinstall the server OS in some cases) and see whether everything is indeed repeatable and deterministic. This will really save your back in cases of the server being irreparably corrupted, especially in combination for the backups of the persistent data.

    I think Ansible hits the sweet spot for repeatable setups, even more so than Nix and NixOS because of its ease of use. When combined with self service for provisioning the architecture, it feels like you have superpowers. Now, some people would also mention Terraform here, but in my experience the actual servers can definitely be provisioned manually on smaller deployments.

  • layers Containers (Docker, Docker Compose, Docker Swarm, Hashicorp Nomad, Kubernetes (Rancher, K3s))

    Containers are a big one for me and the industry as a whole. Even if you use tools like Ansible for making the setup of your infrastructure repeatable, running apps "the old way" causes too much friction. To set up horizontal scaling is an absolute pain: you have to care about directories, systemd services, passing configuration to the apps, resource limits, load balancing, service discovery and a bunch of other things, as well as updates.

    Containers make all of that bearable again, by providing a clear distinction between what belongs to the operating system and what belongs to your app. I do believe that there definitely is and should be this distinction and doing it at a virtual machine and hypervisor level also feels too cumbersome.

    Because of this, I'm really thankful for technologies like Docker, Docker Compose and Docker Swarm, thanks to which I single handedly maintain dozens of apps on about 8 servers in my hybrid cloud. I've also successfully set up many containerized production environments and the entire CI/CD cycle around them, as well as am a huge proponent of 12 Factor Apps to really bring my deployments into the modern day and age.

    Speaking of modern things, Kubernetes can also be useful to the companies who have a strong enough DevOps culture, yet in my experience this is rarely the case. If mandated by corporate policies, then I've found that K3s and Rancher can work well, but almost in all other cases, I'd suggest either Docker Swarm with Portainer, or having a look at Hashicorp Nomad.

    That said, don't just throw your monolith into a container and call it a day. Instead, internalize the 12 factors to make your solution truly cloud native!

  • cached VCS/CI/CD (GitLab (+CI), GitHub (+Actions), Jenkins, Drone)

    Even if your application follow all of the best practices, that's still not enough for them to lead to success! I'd argue that the way they're deployed also should be as automated as possible, in addition to the configuration of the infrastructure that they'll run on as well.

    To this end, I've had plenty of experience with integrating GitLab CI, GitHub Actions and even Jenkins for many different builds, tests and deployments. Admittedly, Jenkins has proved to be a brittle and unstable solution that's somewhat overused within the industry, yet like many other people, I haven't always been able to escape its clutches.

    My personal darling in this regard would be GitLab CI, which can be self-hosted and can run on containers, like Drone, and therefore affords you the ability to utilize your own infrastructure for builds in some pretty efficient ways! In addition, applying GitOps to CI/CD is pretty awesome as well, with which GitLab plays nicely, thanks to its YAML format.

  • public Web servers (Apache, Nginx, Caddy and certbot with Let's Encrypt)

    In my past, I've seen deployments where the actual application servers attempt to handle routing, SSL/TLS termination and other concerns. In my opinion, this is wrong. Even if you don't have a clear network routing mesh (a la Consul), then there are still concrete benefits to using separate web servers, whether containerized or not.

    For example, it's extremely easy to handle app redeployments without affecting the reachability of the endpoint (you can either have a larger timeout and queue requests up until the app is restarted, or even just redirect to a temporary info page about the restart), in addition to which renewing SSL/TLS certificates with certbot or web servers that integrate similar functionality, like Caddy, is really good!

    Lastly, I enjoy the idea of having the concept of a separate ingress - you can definitely rely on web servers or load balancers to route your traffic, instead of having to remap weird ports like 8080 or 3000, or even deal with context paths, which is especially problematic in some Java deployments.

    In my experience, Caddy hits the sweet spot between functionality and usability, given its excellent ease of use - though one has to give Apache and Nginx the props for being so resilient, even if largely legacy software. I'm also looking forwards to exploring Traefik in more detail later.

  • storage Network file systems (NFS, Samba)

    There are many ways to handle persistent data and sharing it amongst many nodes (such as SSL/TLS certificate files in cases when there is more than one ingress point). Some use distributed file systems, like GlusterFS or Ceph, however in my experience they're difficult to set up and have significant overhead.

    In contrast, in most cases I've found that even with container deployments, counting on the underlying file systems with additional mounting mechanisms is more than sufficient! For example, you can just set up a NFS mount with Ansible and then use bind mounts for your containers to share this data in a hassle free way.

    Personally, this is one of the domains where I've found the simplest solutions to be the best, alternatively attempting to eliminate as much of the duplication as you can - having most of the application within your deployments be stateless and for you to know precisely where the stateful data is, both for backups and manual review when needed.

  • cloud_done Monitoring and analytics (Zabbix, Matomo, Apache Skywalking or JavaMelody)

    Even if your apps are running, then there still is the question: "For how long will it stay that way?"

    Experience shows, that all sorts of problems are not a question of "If?" but rather a question of "When?", so some thought should definitely be put into monitoring and analytics. Now, as someone who prefers self-hosted and non-vendor-locked solutions, I've had good experience in that regard with Zabbix, Matomo and Apache Skywalking, all of which offer a part of the overall equation. Ideally, you'll be able to discover all sorts of problems before your clients or customers will and address them quickly enough.

    Also, in my opinion, it's extremely useful to apply all of these even to your development environments, so you're aware of how efficiently you're utilizing the available resources, which can motivate you to further increase the density of your deployments.

  • cloud Cloud and on-premises deployments (AWS, Azure, GCP (but mostly affordable ones) and open source platforms)

    The cloud is often touted as the future of computing. I won't contest, that there are many benefits to allowing large corporations handle some of the more common concerns in regards to provisioning your infrastructure, or even selectively integrating your solutions with SaaS APIs and such. At the same time, however, relying on the cloud too much can lead to your using managed offerings and eventually ending up vendor locked. There is a saying that "Noone ever got fired for picking IBM", which can nowadays be applied to building your solutions on AWS managed services, yet I don't believe that it's okay to choose your options so haphazardly.

    While I do have past experience with such approaches, personally I also really appreciate the possibility of using open source solutions and self-hosting them, especially in the case of everything-aC (where id can be infrastructure, platforms or services) thanks to Docker and tooling around it. Why should I overpay for external logging or analytics solutions, when I can host my own and have all of the data also be stored locally? That does take some technical acumen, which is true, yet in the context of GDPR and data leaks, it's definitely worthy of consideration. Furthermore, my current cloud is about 5x less expensive than hosting it on AWS would be, and around 10-20x less expensive than using managed services would be.

DB

Many of the solutions in the industry would be much better, if more attention and care would be spent on the schema design and engineering the best database possible for the application. In a similar way to the "back end for front end (BFF)" approach, I think that interoperability betweent the database and the application should be a priority! Of course, while I believe that relational databases are the best and sometimes the only solution for many of the projects out there, at the same time I also have some experience with non-relational databases and key-value storages, as well as object stores.

  • storage PostgreSQL (my favourite relational DB, also PostGIS is great)

    If you're in doubt about which solution to use for storing data in your traditional application, most of the time PostgreSQL will be a worthy candidate! It conform to SQL standards pretty well, offers a variety of features for advanced data processing, such as procedural in-database processing with pgSQL and custom data types, whilst also having good performance.

    Not only that, but the PostGIS spin on it is capable of being used for a variety of geospatial data processing and either of those is able to be spun up in as many containers as you need, with sane configuration options and absolutely no restrictive licensing terms whatsoever. Throw in wide driver support and you have arguably one of the best modern solutions for relational data processing.

  • storage MySQL / MariaDB (relational DB for simpler cases)

    I've found both MySQL and MariaDB to be more limited than PostgreSQL, yet at the same time they're still a good and popular choice for simpler systems. Ones where procedural languages won't be what you'll use as often and where you're not looking for custom data types.

    In my opinion the strongest suit of both of these, is the tooling around them - in my experience the MySQL Workbench is hands down the best tool for interfacing with a database management system and schema-first database design. In short, it simply leaves pgAdmin and SQL Developer in the dust.

    It's also perhaps the only piece of software that has excellent forward engineering capabilities, such as drawing ER diagrams, turning them into code for the schema to be created on a live instance of a database, or alternatively synchronizing schema changes after changing the diagram.

  • storage Oracle DB (an unfortunate necessity sometimes)

    I dislike the Oracle DB. I will admit that objectively it is a capable piece of software that often leads to mediocre success in enterprise systems, in part thanks to its support for a variety of complex functionality that can easily rival that of PostgreSQL.

    Yet, there are certain things that I find myself unable to overlook - everything from the restrictive licensing terms, the lack of official and stable container images to use for development, the predatory limitations of Oracle XE, the large amount of resources needed to administer it, as well as comments surrounding the code quality.

    If you've been strong armed into using it, then sure, you don't have a choice, but otherwise I'd suggest that you look for better options out there and perhaps support the development of PostgreSQL or MariaDB with the resources that you'd otherwise spend on licenses.

  • storage SQLite (an underrated gem)

    Most of the time, people believe that what they need is a database management system that can be deployed to a separate server and will serve numerous back end services simultaneously. Yet, there are plenty of situations in which that would provide no fungible benefits, such as in this case of a blog site, or perhaps mobile devices.

    There, DBs like SQLite allow storing the data within a file in the file system and access it directly. For starters, you eliminate a network hop and therefore the latency is almost non-existent. Furthermore, there's no risks about the database not being available at any given time. Not only that, but SQLite is an extremely well tested codebase, it's free to use, easy to get started with and easy to integrate within most projects.

  • widgets MongoDB (a passable non-relational data store)

    MongoDB has almost a cult-like following in some instances, while at the same time it does get a lot of bad rapport online, sometimes rightfully so. That said, I still think that it's one of the better options for storing documents and data that can have very loose relations, if only because of its popularity and therefore the ecosystem that's been built around it.

    Personally, I'd think twice before employing it in my projects, but as a whole, it definitely has its place in the industry. If your system fits its design principles well and the domain is simple enough for you to be able to cope with its deficiencies, definitely consider using it.

  • widgets Redis (my preferred key-value store)

    Redis is fast, simple and dependable. Furthermore, it's open and widely supported in its design.

    Whereas I'm at best cordial in regards to MongoDB, I rather enjoy the thought of utilizing Redis for non-persistent and non-critical data in a variety of different settings. For example, I believe that its perfect place lies either in caching data, or storing shared and temporary data, like user session information.

    I've seen far too many projects where sessions are stored within the application memory, which has pitfalls that are twofold. First, not using a key-value storage like this means that the data in memory will get cleared every time the process restarts, short of a file-based storage mechanism. So, if you restart the application, everyone gets logged out, which is unacceptable. Secondly, if you want to scale horizontally but don't have sticky sessions, your system will work awfully inconsistently, because the instances will rely on local data which will not be shared across different network requests to different instances.

    Seriously, don't fear Redis (as long as you don't put critical data in it).

  • widgets S3 (a pretty good object storage solution)

    Sooner or later you'll need to store files. Other times, you'll just need to store arbitrary blobs of binary data. MongoDB can work for that, however there are tools that are far better suited for it. One of such tools, in my experience, is S3 - more of a set of standards rather than a concrete implementation, of which there are many, even outside of AWS. It's relatively simple to get started with and I've used it to much success in many projects and CMSes, since storing files and similar units of data within a DB feels somewhat icky.

    In short, if you need to store stuff like that, consider the potential file size, contents and then look at either some of the open implementations of S3, or maybe look at GridFS within MongoDB.

My views as a developer

There are plenty of qualities that a good developer should have, or even many that will affect whether a developer will be a good cultural fit in a particular environment. Because of this, I do believe that transparency is indeed the best policy, so that everyone can find the circumstances in life which suit them best! To make this easier, I've decided not to shy away from telling you a bit about my views regarding software development, many of which are candidly listed below.

  • cloud_done On tools and platforms (tools and platforms matter)

    Personally, I think that there is definitely some wisdom to the things outlined in The Joel Test, notably, in the "Do you use the best tools money can buy?" suggestion. In my experience, it's immensely useful to invest in good tools, such as the products by JetBrains, for which I own the ultimate license.

    That said, I've also noticed a worrying trend in the industry - people pigeonholing themselves into using only paid platforms. For example, if you build your entire application around the offerings of AWS, Azure, GCP, or any of the other PaaS/SaaS vendors, you'll soon find that it will become impossible for you to ever migrate to anything else and you'll be stuck dealing with their costs. That's reasonable when you're a large company with money to burn, or just want to pay someone else to deal with providing managed services, but can also be very wasteful. That's why, even though I'm okay paying for tools (only when there are free alternatives, such as Visual Studio Code in my IDE example), I am also a proponent of open solutions.

    I believe that you should strive to just use those cloud vendors for VPSes and build everything within them on open technologies - personally, using Docker, Docker Swarm, a platform like Java/.NET/Node/... for the back end application, React/Angular/Vue/... for the front end, Caddy/Apache2/Nginx/... for web server and something like PostgreSQM/MariaDB/MySQL/MongoDB/... for data storage has served me immensely well. Because of the above choices, all of the sudden, it doesn't matter anymore where my application are running, be it locally, on-prem, or in any of the cloud vendors. And in practice, that means I don't have to rely on the aforementioned expensive trio, but instead can utilize vendors like DigitalOcean, Scaleway, Hetzner, or my current favourite - Time4VPS.

  • extension On software architecture and finding balance (a bit more information about how I approach development)

    I do believe that developers should be aware of the ways to develop software and make meaningful decisions about how to solve problems. In addition, thought should be given to how these choices will impact the future of project. In this regard, I've seen two worrying trends in the industry.

    On one end of the spectrum, there are both teams and companies who don't believe in finding the best tool for the particular job, and instead attempt to standardize everything on a singular stack or technology. For example: they need to store session data? Just put it in the DB. They need to store some temporary data? Just put it in the DB. Need to store files? Into the DB they go. Message queues? The DB. The problem with this approach is that after a while, tools that aren't well suited for a particular problem get used for it anyways, which makes everyone's lives harder. Furthermore, this ludditism can impact the architecture as well - before long, they'll be running everything into a singular monolith that's probably also not scalable, essentially creating a single point of failure.

    While the previous group might fear new technologies, the next group is largely enthralled by the idea of CV driven development, chasing after all of the shiniest technologies in an attempt to embellish their CVs to later find a better job. I cannot personally support this approach, because I've seen what it can lead to - they'll pick Apache Kafka when RabbitMQ or even ZeroMQ would do. They'll pick GraphQL or gRPC over REST, even when there are no fungible benefits to that. They won't even do a risk analysis, before picking Kubernetes and a microservice architecture for their projects, even when they don't have the resources to deal with the complexities of this choice. Eventually, they might just exit the company with a long list of technologies that they've used, leaving behind a wasteland of one service per person, the OpEx having been unreasonably bloated.

    It is not my goal to have the biggest CV around, nor is it my goal to sit within my comfort zone. I do believe that as an engineer, I should strive to find the balance between stable and tested technologies and those that actually solve problems in novel ways. To this end, I believe in employing both my past experience, the experience of others as described in numerous technical blogs and writeups, as well as testing, proof of concept systems and MVPs, to find the best solution for the given circumstances. And perhaps on a more humorous note, I think it's indeed a good idea to evaluate choosing boring technology sometimes for its known unknowns and predictable behaviour.

  • loyalty On taking responsibility and ownership (to me, development is more than just a 9-5 vocation)

    As a developer, I want to succeed.

    My highest standard for success is not taking home a wad of cash and not caring about the success of the projects that I work on. Wherever I go, I want to leave good, working systems which solve the problems for which they were designed. To that end, I find that taking ownership of the parts that I touch and design leads to success more often than just putting out the fires after someone uncaring has caused. It's undeniable that occasionally outages happen and blameless post mortems can be immensely useful, yet I've had the displeasure of standing in governmental offices and seeing a queue form because a system refuses to work, the original developers being long gone and absolved of any responsibility for it. Later that day, I did pull out the guts of the system and replace them with application that were more resilient and actually averted that outage, yet it made me feel strongly about seeking out environments in which i'm given the creative and engineering control to avoid such occurrences entirely, to the best of my abilities.

    Because of this, I want to be responsible for the implementation of new services from day one. I want to make the architectural choices that are best suited to tackling the particular tasks that it needs to do. I want to be the one who consults others about their experience and views on things, before finding the best solution. I also want to be the one who'll provide some pushback to management or clients when absolutely necessary, to tell them about the benefits of monitoring, analytics, automation, test coverage, CI/CD, or even running some of their workloads within containers. I will cope with pre-existing conditions and quirks, of course, yet I want to do whatever will lead to success.

  • code On writing code (the technical bits also deserve mention)

    Despite all of the social aspects, at the end of the day, a developer still needs to actually write code.

    After all of the planning and discussions are done with, there are also a few things which should be remembered when about to make computers bend to our bidding. For starters, I believe both in writing code that's self explanatory through its variable, method and class naming, explaining what it does, as well as commenting it - no matter how clear the variable naming is, those won't express why the code exists there and what the underlying business requirements are. Then, there's the question of following principles like SOLID or DRY, but personally I don't take these to the point of them becoming a mantra, as some people do.

    In my experience, careful application of YAGNI and the rule of three has similarly good results. In my experience, it's very good to do a litmus test or two every now and then - just stop and ask yourself whether what you're doing actually makes sense and gives any fungible benefits in the near future. If not, it's entirely possible that you're stuck in a loop of cargo culting which I do my best to avoid. For example, if you're creating an interface for every class, yet 90% of the interfaces within your project have just 1 implementation, you're probably doing something a bit wrong, especially since by the time you'll actually need an interface, your IDE of choice will probably be able to extract it with no hassles.

    Lastly, I believe that code should not only be easy to understand and utilize, but also easy to both modify and also remove. Despite even the best intentions, sometimes a component will just no longer belong within a codebase. Be it through modular design or loose coupling (without getting too lost amidst abstractions), there are plenty of methods to achieve this, which I strive to do.

  • thumb_up On collaboration with others (development is never just a solitary technical activity)

    In the ICT industry, there is a somewhat toxic stereotype - of the developer who's a technical genius, but also a total thorn in people's side. A person that solves most problems, but is a lost cause when it comes to working with or teaching others. I believe that such behaviour and way of carrying oneself should never be excused. The true 10x developer is not the person who chugs energy drinks and types code on 2 keyboards simultaneously (just a small joke about the portrayal of programming in media) whilst being an excellent individual contributor, but rather someone who enables another 9 people to do their work more easily and helps them.

    Because of this, I believe that it's important to have the team cohesion be as good as possible - to have everyone remain professional, yet polite and for the team members to be on friendly terms. I'd argue that it's worthwhile to see that your RACI matrix within the company is expanded and that the exchange of information happens freely and is encouraged. That's why I pick my battles and sometimes concede on sub-optimal technical decisions, if they mean meeting the immediate needs of the busines, the team, or even the other developers around me, be it because of their familiarity with a particular technology or something else.

    That said, I do believe that collaboration should always go both ways. The COBIT framework talks in detail about alignment of the technical goals to those of the business, but in my experience, sometimes business processes should also be re-engineered to fit what's technically feasible. The more inclusive and diverse a workplace, the more people are able to contribute to the decisionmaking process, the better the end result could be - that's why so many open source projects thrive. Servant leadership should be embraced within teams and people should take precedence over processes, as originally described by The Agile Manifesto.

    Not only that, but research shows that companies with strong engineering leadership excel at their craft. To that end, I'm more than happy to openly share the results of my work in internal or open seminars, to organize workshops and to develop proof of concept systems, to build trust and collaborate with others at all levels of seniority, to mentor younger developers and to document decisions and functionality with the due diligence.

    Developers definitely can have strongly held views and their code could reflect these measured choices. Yet, the developers themselves should not get too caught up in their own egos. This simple thought deserves a bit more recognition within the industry, since engineering software is often a social and collaborative activity.

  • school On lifelong learning and self-improvement (because nothing will kill a craft like stagnation)

    Near the start of my career, in one of the software development conferences that I attended, a rather serious looking gentleman talked about his long career and the many things he's worked on. It was pretty curious to find out that he never stopped learning new things, be it on the job or in his own time, given his passion for software development. Some of what he said resonated with me: that every 3-5 years you should refresh your skills, because things in our industry can change at a rapid pace. Back then, almost noone had heard of Docker and by the time it became an industry standard, I had already been an early adopter and therefore spearheaded the effort to introduce it within my company to great effect.

    Obviously, it's not possible for me to learn every single technology that's worthy of my attention within my working hours, which is why I also treat my career as a lifestyle - I write code and explore new technologies in my free time and on the weekends. Side projects are a wonderful way to explore new things and learn useful skills and ways to solve problems in a low risk environment. However, if there is one thing that's a definite must in any potential employer, it's support on their part to this drive of mine to improve myself. I expect the ability to also attend software development conferences and events, like Riga DevDays, DevTernity, FrontCon and many like it, be it in person or remotely, in order to also see what some of the other wonderful people within the industry have done.

    Not only that, but I'll greatly appreciate funding for me to purchase programming books and/or subscriptions to online learning platforms, which can also be useful. Lastly, I'll absolutely love it if you guys encourage improving internal tools and such, or maybe even have internal hackathons. Also, I recognize that learning is a journey, therefore you won't find me engaging in elitism or gatekeeping.

About me as a person

Of course, it's not enough to just be a good developer with beliefs that ensure engineering excellency in the long run - if the person is not pleasant to work with, that will both hold them back and make those around them somewhat miserable. While I personally attempt to leave many of the aspects of my personal life "at the door", so to speak, and always attempt to remain at least somewhat professional, I don't believe that that means I should hide who I am as a person and what my beliefs are.

  • mood My personality (who am I, really?)

    Despite me participating in numerous software development events, conferences and workshops, the people who are close to me actually know me as someone who's rather introverted. I don't have a problem with visiting clients for some architectural discussions, or maybe even going to some fun team building exercises with my colleagues (the most awesome that come to mind being laser tag and going kart racing), yet in my private life, I prefer to keep a closely knit group of friends in whom I can confide in.

    That said, I attempt to be a pretty non-confrontational person in my professional capacity, always attempting to offer solutions to problems, have productive discussions and even offer constructive criticism, in an effort to make any of the workplaces that I participate in feel welcoming. I believe in both equality and diversity, thus you won't see me being impolite to those who are different than I. I support human rights in all of their forms - people should be treated well, regardless of their sex, gender identity, orientation, ethnicity, nationality, political or religious views, or any other qualities, as long as they return that same human decency.

    However, I don't necessarily believe that the workplace is where people should go to discuss some of the things above, given that these topics can be polarizing and not necessarily contribute to the goals of why everyone is there in the first place. Because of this, in the workplace, you'll probably find me to be a bit reserved.

  • terrain My hobbies (since I do more than just write code)

    Outside of work I also have quite a few things that I enjoy doing to pass the time! There are plenty of technical things, such as working on my homelab and doing little side projects, in an effort to some day be able to write something to help others solve real problems (because of which I support the open data initiatives of my government). In addition to that, I also enjoy a bit of 3D modelling and content creation, both for visualizations and some game development, even if I don't always have time for that sort of thing. Curiously, some of these skills also carry over to 3D printing, in which I also partake in.

    Apart from that, I also remain active - since a while ago, I've started jogging in the evenings, currently doing about 4 kilometers at a decent pace, in addition to doing pull ups, push ups and sit ups. Latvians actually have a saying, that goes along the lines of "within a healthy body lives a healthy mind", which I've come to respect. This taking care after myself also extends to what I eat - not too much, mostly vegetables, occasionally enjoying a bit of meat for celebrations and the like. That said, I also enjoy trying out vegetarian meals, just to see how they compare with the more conventional dishes. Oh, and attempting to have a healthy sleep schedule also plays a part in my life!

    Furthermore, I also enjoy reading books in my free time, in particular some science fiction series, such as "The Three-Body Problem", "Red Rising" and "The War of the Worlds" being some of the last ones that I read. Actually, a dream of mine is to write some fiction of my own some day! Of course, like many other people I rather enjoy watching a variety of movies and shows as well, the likes of "The Expanse" always having a soft spot in my heart. I mean, who doesn't enjoy a bit of science fiction that seems realistic, yet explores a variety of interesting concepts!?

  • map My aspirations (where I want to see myself in 5 years)

    I'd say that for the time being, there are three large goals in my life. The first one is to become someone dependable - a person that my friends can turn to in their time of need, and to be able to help them with whatever it may be. This does necessitate having good control over my life and therefore I do spend a lot of time working on myself, both physically and mentally.

    Secondly, I also want to be someone who is at the top of my craft. It does take conscious though and effort for this aspiration not to become toxic, because there will always be someone who's a few steps ahead of me, however that doesn't excuse me from continuously learning new things to improve my skills and broaden the horizons of my knowledge. As a developer, I want to be able to either pick up or learn almost any of the popular development stacks out there, and to be able to generate value and create software to solve problems with them. As a professional in the broader sense, I want to be able to see software through the full development cycle, from the conception of the idea, to it running in production environments.

    Lastly, I seek financial stability. For an employer, that might mean me constantly seeking out ways to improve my usefulness to them and climb the figurative career ladder, taking on additional responsibilities as I go along. Personally, however, this means having full control over my own income and expenses, so I always know where my money actually goes. This also implies me living a fairly spartan lifestyle, in opposition to blind consumerism and buying things I don't need. For example, I don't splurge on expensive clothes or status symbols and I oppose e-waste, most of the CPUs in my homelab are actually low power older generation ones which have been refurbished (200GEs, in case you're curious).

  • done_all The challenges that I face (nobody's perfect)

    In my career, I've seen small details being overlooked and having a larger impact down the road, which sometimes makes me double check both my own work and that of others, sometimes slowing me down. Professionally, this implies me trusting others, but verifying whether everything is indeed as it should be, which, on the flip side, has saved our hides in some production deployments in the past, actually.

    Furthermore, as the copious amount of text above shows, I'm a bit opinionated - over the years, I've built some views that have successfully seen me through a number of projects, however which might not necessarily coincide with those of other people around me. Because of this, I make a conscious effort to pick my battles, so to speak, and find compromise, even when I disagree.