An Engineer's Log: No Such Thing as a Typical Day

When I joined Infobip fresh out of college, I couldn't have imagined that I'd be sitting here today and giving you my firsthand experience of a day in the life at Infobip in our lively Vodnjan office.

Back then, Infobip was relatively unknown to the public. People knew we had offices worldwide and were involved in message delivery, but the specifics were unclear. It's a different story now since our presence in the media has grown, and you've probably had the chance to read a lot about what we do - but nothing beats hearing about it from someone in the trenches.

But here is a catch: There is no such thing as a typical day at Infobip, and no two days are ever the same.

From office to home to hybrid

Let's take a little throwback to 2020 when we all got hit by the Covid pandemic. Infobip swiftly decided to prioritize the safety of its employees and closed its offices in Croatia early on, transitioning us all to remote work. Looking back, I think that was the right move, putting the well-being of employees and their families first.

I did miss my time at the office, working alongside a group of senior engineers. Coffee breaks were filled with engaging conversations, and I absorbed everything the seniors had to say. Their knowledge and their ability to swiftly provide solutions to my problems were simply impressive, and so were the learning opportunities.

So, after two years of remote work, communicating via Slack and Teams and asking those big questions like "Can you see my screen?" and "Can you hear me?", a team decision was made. Five of us from my team decided to return to the Vodnjan office, resuming full-time work from there. Naturally, this meant reintroducing the daily commute into my routine, but everything else far outweighed any inconvenience it may have brought.

Morning routine

My day starts like this: I wake up at 5:00 AM to do my morning workout, come home, take a quick shower, make myself a French toast omelette sandwich, meditate, read a book… Just kidding. I wake up at 08:00 AM, skip breakfast and hop in my car. The 15-minute drive from Pula to Vodnjan is accompanied by my favorite playlist..

The Pangea campus, where I work, is a bit of an architectural marvel; wood, marble, and huge windows overlooking the Brijuni islands are not a bad way to start the day.

After logging into my PC, I promptly check my email, glance at my calendar, and catch up on any missed Slack replies. Most of them are in our team support channel. There are around 700 members from different departments reporting issues and seeking assistance from my team there. Every day brings a set of different questions, and as a team, we try to respond promptly and provide as much help as possible.

With no immediate issues to address and fellow team members gradually arriving, we gather for our morning coffee ritual. I ask our favorite barista, Jadran, to prepare a delicious macchiato while I quickly grab a fresh croissant from a nearby plate. On the campus terrace, we join another team enjoying the sun. We were all slightly sleepy, but the conversation soon became lively. One colleague shares how she leveraged ChatGPT to enhance her Jira responses, leading to a discussion on various AI tools and their use cases in our work. This is one of those moments I'd missed working from home.

Among my team of eight, five of us regularly work from the office. As part of the CPaaS layer of Infobip's tech stack, our responsibilities revolve around a suite of services operating on our core messaging platform. So our morning coffee sessions are opportunities for open discussions, sharing experiences, seeking advice, and syncing on the tasks at hand.

Morning coding

I return to my seat and kickstart my development environment. I open IntelliJ IDEA, my editor for Java development, and Jira to check the progress of our sprint. Since our sprint is two weeks long, I have plenty of time to complete my assignments.

Next, I open our Bitbucket git repository to review the pull request I submitted yesterday. I like receiving comments on my pull requests because they show that someone has invested their time in reviewing and thinking about my code. For substantial code changes, we go into a meeting room to discuss them collectively, finding it more convenient and easier for everyone to understand.

After addressing the pull request comments, I shifted my focus to the pull requests assigned to me for review. As I analyze the code, it becomes evident that an if statement could be inverted and moved to the beginning of the method, allowing for early return and avoiding unnecessary nesting. After some time, I finish the review and return to my IDEA code editor to continue working on my assigned task.

I'm working on a test to validate a recent code change I made in one of our core messaging service's API endpoints. Given the potential impact on message storage, billing, and client reports, writing tests is crucial. I mock the service calls, create a service request and validate the response. Satisfied with the test's outcome, I proceeded to fire up a few local Docker containers that serve as dependencies for my service. With my service up and running, I execute the test. Success!

Suddenly, a Slack notification steals my attention. It's a question from one of my teammates. He is working on a web service that needs to connect to a distinct set of Elasticsearch hosts. Preferring to avoid static configuration, he opted to use one of our internal services, which allows him the periodical querying to fetch the updated hosts and more. We discuss the approach and validate his idea. Satisfied with the agreement, he proceeded with the implementation.

When in doubt, seeking advice and consulting with team members is always a great idea. Nothing is worse than realizing you've gone down the rabbit hole after investing too much effort.

As I settle back into my code editor, a notification pops up, signaling a Slack call. The flow of productivity pauses as I join our daily meeting call.

Daily meeting

I join my team daily, slipping on my headphones and promptly muting myself - a small action that will later prove to be a hilarious mistake when it's my turn to speak. As a self-managed team, every two weeks, someone else from the team leads the sprint ceremonies: daily meetings, sprint planning, grooming, retrospectives, etc. We go through each team member's tasks one by one.

As it's my turn, I begin speaking, but no one is saying anything back. After some time, someone finally says: "Hey, if you're talking, you're probably muted because we can't hear you." A video conference classic!

The daily facilitator asks about the progress of my tasks and whether there are any blockers in my work. I assure them I'm on track and will soon deploy the code change to a test environment once I finish running all the necessary tests on my machine. If any issues or blockers required further discussion, we would schedule a separate call after the daily is complete to keep the call short. With everyone providing updates on their progress, we finish the call, wrapping up in just 17 minutes - a highly efficient meeting, by my standards.

Back in my code editor, I focus on writing tests, tests, and more tests. After all, this code change won't make it into the master branch without proper test coverage. I execute the tests, and, to my despair, they fail. Oh, why is this happening!? Ah, it turns out I was validating the wrong thing. Swiftly correcting my mistake, I rerun the tests, which pass this time! I push my changes to Git, and like magic, the Jenkins pipeline automatically picks it up and initiates my build.

Off to lunch

I step away from my desk, ready to enjoy lunch with my team members as we eagerly discuss today's lunch menu options. A quick glance reveals some great choices: corn soup, pasta with shrimp and zucchini, chicken risotto, salads, and desserts. As I discuss the menu, I'm reminded of yet another great perk of working in the office - free lunch!

It's hard to focus on tasks with an empty stomach, so it's time to indulge in some well-deserved... om nom lunch! I make my after-lunch coffee myself at the nearest coffee machine on our floor and drink it up.

Deploy the code changes.

With the successful completion of the Jenkins build and all tests passing with flying green colors, I'm confident I have a fully functional Docker image ready for deployment. Thanks to our Deployment Manager tool, I can manage our services across different data centers worldwide with just a few clicks!

As the deployment progresses, I closely monitor the logs scrolling across the screen, taking another sip of my delicious coffee. The screen flashes with the reassuring color of green, signaling that everything is likely up and running. I quickly switch to the output logs tab, examining the details to ensure all is correct.

Next, I open our Graylog tool, prepared to investigate any potential errors on the particular instance I deployed just now. Fortunately, luck is on my side today, as I find no errors to address. With that assurance, I let our testing team know they can start running their tests at their convenience.

Off to another challenge

With my current task of cooking on IO, I shift my focus to the second assignment in the sprint. This one involves a mix of investigation and development, which means syncing with another development team and stakeholders to align with upcoming changes.

My responsibility is to use this extended response from another service and update our messages to ensure the successful submission of messages to different mobile network operators. To achieve this, I have to ask myself some key questions: How should we handle null values? What if it's not null but empty? What occurs during call retries? What if the message is multi-part? Should I apply changes to all parts? With these questions, I quickly draft some tests to cover these scenarios.

Planning & estimations

Meanwhile, the testing team returns with a green checkmark for my previous task, which means it's ready for a pull request! As I create the pull request for the team's review, I receive a meeting notification for a new project we're undertaking — just 15 minutes away. I swiftly refresh my memory by reviewing old meeting notes related to the project.

During the meeting, the project manager asked for an estimation of the effort required for a specific app functionality, which I must translate into the number of API calls, database queries, and the amount of validation and business logic needed to achieve it.

With several other development-side inquiries to address, such as deployment plans, we finalize the meeting and agree on the next steps. Feeling a touch tired, I decide it's time for a much-needed coffee break and a chance to stretch my legs. Meetings can be taxing, especially when predictions are necessary, but I always rely on past development experiences to gauge the timelines.

Deploying to production

After the break, I return to my seat to check on the progress of the pull request. It's been approved by team members and is ready for merging! However, deploying to production is no small task. I notify the team on Slack of my intentions to deploy the latest version, receiving a stream of funny emojis as acknowledgment.

I initiate the canary deployment, which deploys one instance and monitors metrics compared to older versions. Once everything checks out, the fresh version is rolled out to all 150 instances across over 20 data centers. I inspect the Grafana dashboard just in case and check the error logs on Graylog to ensure everything is proceeding as planned. With all systems looking good, I leave the deployment to do its thing.

Wrap up

Returning to the code editor, I finish the remaining tests, typing, mocking, asserting, and validating. As I run the tests and examine the results, time flies, and the previous deployment is successfully completed. All statuses on different data centers proudly display green, signifying the latest version is deployed everywhere! I update our Jira sprint dashboard, moving the task into the satisfying "Done" status.

Finally, I push my changes to Git, letting our Jenkins build handle the rest. As the day comes to a close, I check Slack for any remaining queries, ensure the service dashboard looks good, and gradually shut down everything until tomorrow — when new challenges await.

Last updated