Monday, 1 September 2025

Technical Design Document

In software development, we often move fast—especially in agile environments. But moving fast doesn’t mean skipping structure. One of the most important tools to ensure alignment, clarity, and quality is the Technical Design Document (TDD)

It’s not just for architects or senior engineers; it’s something every developer should know how to write. A well-written design document saves time, reduces misunderstandings, and ensures the team is building the right solution for the right business problem.

Why a Technical Design Document?

Whenever we need to introduce a new system component into an existing system or change the current architecture, it must be done in a way that aligns with company policies. 

In a waterfall setup, this document is usually written only by an architect with many years of experience. But in an agile environment, it’s often created by any member of the team. That means even someone with just a year of experience should know how to write it.

What Needs to Be Included in the TDD

I believe the TDD should have 3 sections, and each one should be finalized and approved before moving on to the next.

1. Introduction Section

The programmer needs to define the scope of the problem and explain why it’s an issue—mainly from the business perspective, not the technical one. 

If the problem has no business impact, why solve it? Some problems may not seem to have a direct business effect (like poor database design or spaghetti code), but in reality they do—causing timeouts, bugs, and delays in adding new features. This section should determine whether the reader continues with the document or not. 

Highlight the business requirements and translate them into a checklist that any solution must satisfy to be acceptable. I recommend finalizing this section before diving deeper, since changes here can affect the entire document.

Good examples: lack of systemic communication with users, poor retention rate, 1 out of every 3 orders failing permanently due to database errors, or order processing time being 12 minutes slower than the market average.
Bad examples: bad DB schema with many nulls, code being hard to onboard or edit, frequent deployment failures.

2. Solution Discussion

A design document should propose a single solution. There may be many possible approaches, but you need to compare them, pick the best one, and justify your choice. Once you’ve selected a solution, dive deeper and describe possible sub-solutions.

For example, if your solution is to design a microservice, then sub-solutions could cover which database to use, how the service communicates with others, and what the abstract interface looks like. 

Another example is migrating a service—sub-solutions here might include how to handle outage time, and how to sync old data with the new system.

This section should also include the high-level flows. Finally, explain how this solution fully addresses the problem, ensuring that every item in the checklist is covered.

3. Timeline and Components Discussion

After agreeing on the solution, it’s important to write a section that breaks the work into features, assigning each with estimated time, priority, and whether it depends on another phase. 

A common mistake here is dividing the work vertically (layer-based) instead of horizontally (feature-based). Remember, in agile we want to deliver as soon as possible. If you build the entire database layer, then the business layer, but don’t deliver a single usable UI or API, you’ll only get feedback very late in the process—and that will backfire.

This section also gives stakeholders the space to decide whether this solution should be developed right now or if other priorities come first—meaning it might be delayed.

Final Thoughts

At the end of the day, a technical design document is not just paperwork—it’s a communication tool. It aligns engineers, product managers, and stakeholders on why a problem matters, how we plan to solve it, and what it will take to get there. Writing a good one takes practice, but it’s a skill every engineer should develop early. It’s one of the best ways to ensure we’re building solutions that are not only technically sound but also meaningful for the business.

Another big benefit is onboarding: when each part of your system has a document describing what it is, why it exists, and how it works, new team members can ramp up much faster.

Thursday, 10 July 2025

Interviewing in the Age of AI – Why the Hiring Process Needs to Change

One thought I’ve been wanting to talk about for a while is how hiring should change now that AI is changing everything around us—including how people apply and how companies hire.

A Quick Look Back

A few years back, things were simpler. There was a quick screening call, maybe an onsite interview, and that was enough to decide if the person is a good fit or not. Then companies started using online tools to make the process easier: assessments, take-home tasks, Zoom interviews, and systems to auto-filter CVs (ATS). It made scheduling and logistics easier, and although there were some concerns about cheating, it was still manageable. Tools could catch it, and honestly, cheating wasn’t as common or as easy as it is now.

The AI-Driven Landscape

Today, we need to look again at every step in this process. Most CVs now are optimized using AI just to pass the ATS and make the candidate seem like a perfect fit—even if they’re not. The tasks that used to take a day or two can be done in a few minutes. The online assessments can be solved instantly with AI. All of this makes the modern hiring process harder than ever. Personally, I’ve seen cases where I was sure the person was cheating, and suddenly I’m in a full Detective Conan episode trying to prove it.

At the same time, HR teams and hiring managers are depending more and more on AI because it saves time. And it does help in some ways—it can give feedback on a candidate’s fit, suggest improvements, and even guide people on what they should learn. But the downsides are becoming a real issue.

The Paradox of AI in Hiring

For example, AI-generated CVs often include exaggerated or fake qualifications. I’m pretty sure many people just generate them, don’t even read the final version, and then submit directly. That makes ranking or evaluating real candidates harder than it should be. On top of that, the new online assessment tools track behavior and movement to detect AI usage or cheating, but sometimes they just make people more anxious. I remember before, I used to pause for a couple of minutes just to think about the best way to approach a question. Now, some systems flag that as suspicious behavior—like maybe I’m using a second device. It’s frustrating.

Online interviews aren’t better. Instead of focusing on the actual content, I often find myself trying to figure out if someone is using AI behind the scenes. It’s no longer just a technical interview—it’s like a game of mental chess.

As for take-home tasks, if you say it’s okay to use AI, then fine—it’s fair for everyone. But if you clearly say “don’t use AI,” then you’re basically punishing the honest people. The ones who play fair (and these are usually the kind of people you want to hire) end up at a disadvantage. So ironically, you end up filtering out the candidates with integrity.

Are We Hiring the Right People?

I don’t have exact data on how much AI affects hiring results, but I liked this post that shows how weird the current state is for both candidates and companies:
https://www.linkedin.com/posts/nasserjr_recruitment-process-activity-7267260107128778753-_mnF

And another meme from the same person that really hits home:
https://www.linkedin.com/posts/nasserjr_well-thanks-activity-7292851244702834689-QW0M

The real problem is that while AI saves the company time, we need to ask: Are we actually hiring the right people? And even if we find a great match, what’s the guarantee they’ll even accept the offer?

Final Thoughts

I’m not against using AI in hiring, but we need to adapt. We can’t keep applying old-school interview methods in a world where AI is involved on both sides. The system needs to evolve, or we’ll keep making the wrong calls, for both candidates and companies.

Friday, 4 July 2025

Off-Topic in Software Engineering — Does It Really Not Matter?

Although I’ll focus mainly on software engineers in this post, what I’m saying applies just as much to data scientists, data engineers, QA, DevOps, and honestly anyone working in tech.

While talking with fresh or junior engineers, I’ve noticed something: many topics I encountered during my learning journey are now often seen as “unnecessary for work.” Things like how the internet works, how data flows through systems, or how computers handle memory — they’re often brushed off as irrelevant or “too low-level.”

Perhaps you don’t need them in your daily tasks for now. But that doesn't mean they won’t be useful later.

For example, I’ve had conversations where I mention (in very abstract terms) how browsers work, only to realize the other person doesn't know how data even travels over the internet. Or when I bring up data storage or database internals and hear something like: "I’m a full-stack developer" or "I'm doing ML models — this is outside my scope."

But the truth is: understanding these things — even at a high level — makes you better at what you do. Whether you're debugging, optimizing, scaling, or building something new, having that foundational context helps.

You don’t need to dive deep into every topic. But knowing just enough about what's behind the scenes helps you make smarter decisions. A QA engineer who understands backend behavior can write better test strategies. A data scientist who knows how pipelines are built can spot issues earlier. A software engineer who understands how memory works will write more efficient code.

Think of it like this: doctors study the entire human body before they specialize, not because they’ll use all of it every day, but because it helps them see the full picture. The same goes here.

So if you're early in your career — don’t dismiss things as “off-topic” too quickly. The things you skip today might be the exact things you need a few years down the line. Knowledge compounds — and it always pays off.

Sunday, 22 June 2025

Why Students Should Think Twice Before Overusing AI Tools in College

In recent years, I’ve noticed a growing trend: many students and fresh graduates are heavily relying on AI tools during their college years. While I’m a strong believer in the power of large language models (LLMs) — for code generation, documentation, testing, deployment, infrastructure support, and more — I want to explain why you should not become overly dependent on them during your learning journey.

1. College Is for Learning, Not Just Finishing Tasks

Most college assignments and projects have been done countless times before. So why do professors still ask you to do them?

Because these exercises are not about the final output — they’re about the thinking process. They’re designed to help you build a deep understanding of computer science fundamentals. When you shortcut that process by asking an AI to do the thinking for you, you miss the real purpose: learning how to solve problems yourself.

There are public repositories where you can copy solutions and make your projects run instantly. But that’s not the point — your goal in college is not to finish, it’s to understand.

2. If AI Can Do Your Job, Why Would a Company Hire You?

If your only skill is knowing how to prompt AI tools, you’re making yourself easy to replace.

I’ve seen many people ace online assessments — solving problems involving dynamic programming, binary search, graph theory, and more — only to struggle with the basics during on-site interviews. They couldn’t analyze the complexity of a simple nested loop or explain how to choose between two sorting algorithms.

Overusing AI creates a false sense of competence. If you constantly rely on it to get things done, what happens when you face a challenge in real life — one that requires your own reasoning?

3. LLMs Aren’t Always Reliable for Complex or In-Depth Work

Despite all the hype, AI tools are not always accurate.

LLMs can give different answers to the same question depending on how it’s phrased. They sometimes produce code with compile errors or hallucinate incorrect explanations. Unless you understand the underlying concept, you won’t be able to judge whether the AI’s response is correct — and that’s risky.

AI should assist your thinking, not replace it.

4. Don’t Treat Private Code Like It’s Public

A major concern when using public AI tools is data leakage. Once you paste your code, tasks, or documentation into an online AI model, you have no real control over where that information ends up. Future users asking similar questions might get your proprietary logic as part of their output.

I saw this firsthand with an intern we were onboarding. After being assigned a task (with no pressure or deadline), he immediately started pasting a large portion of our internal code and task descriptions into GPT. He took the AI’s response, submitted it as a pull request — and didn’t even test it.

When I asked him about a specific line in the code, he had no idea what it did. I told him clearly: do not upload internal code, models, documents — anything — to GPT. If you need help or more time, just ask. You’re here to learn, not to impress us with how fast you can finish something.

Unfortunately, he kept doing the same thing. Eventually, our manager had to send out a formal email reminding everyone not to share internal content with public AI tools. Whether it was because of this intern or others, the message was clear: this isn’t acceptable. Yet he still relied on GPT for everything, and we all agreed — he had become someone who couldn’t write a line of code without help.


Final Thoughts

AI is a powerful tool — no doubt. But if you rely on it too early and too heavily, especially during your formative learning years, you’re sabotaging your own growth. Use it to assist you, not to bypass the learning process. Learn the foundations first. Think independently. Struggle, fail, and get better.

You’ll thank yourself later — when you're the one solving real problems, not just prompting AI to do it for you.

For example: this post was mainly written by me. I used AI to review it, then I reviewed the AI’s suggestions and made further improvements. That’s how you should be using these tools — not as a crutch, but as a sounding board to help you grow.

Sunday, 1 June 2025

Why Alarms Feel Broken (and How to Fix Them)

I love talking about common myths in software engineering, and here’s the first one: alarms.

The purpose of alarms is simple — visibility without manual checks. Instead of fetching data, the system pushes alerts when something's wrong. It sounds great, right? So why do alarms often feel like a nightmare?

Let’s break it down.

The Manager's View vs The On-Call Engineer's Reality

From a management perspective, more alarms = more safety. They want visibility over every metric to avoid any incident slipping through the cracks. If two metrics signal the same issue, they often prefer two separate alarms — just to be extra safe.

But from the on-call engineer’s perspective, this turns into chaos. Alarms with no clear action, duplicated alerts for the same issue, and false positives just create noise. Nobody wants to be woken up at 3 AM for something that doesn’t need immediate attention.

The core problem? Neither side feels the pain of the other.

  • Higher-level managers may not have been on-call in 10–20 years — or ever. A dozen P0 alerts a day? Not their problem.

  • Junior engineers on-call may not grasp the full system overview. If it doesn't trigger an alarm, they assume it's fine — which isn’t always true.

So, How Do We Fix It?

Balancing these two viewpoints is the responsibility of senior engineers and mid-level managers. They’re the bridge between hands-on pain and high-level priorities.

Let’s be real: execs won’t care about reducing alarm noise unless it affects a KPI. So change has to start lower down.

Tips to Improve Your Alarm System

  1. Define Clear Priority Levels

    If everything is a P0, your system isn't production-ready. Aim for at least three levels:

    • Level 0 (P0): Needs immediate action (e.g., business-critical outage).

    • Level 1 (P1): Important but can wait a few hours.

    • Level 2 (P2): Can wait days without impact.

    Within each level, use FIFO. If someone asks you to drop a P1 to work on a "more important" P1, your priorities are misaligned; either the more important one should be a P0 or the other be P2.

  2. Align Alarms with Business Impact

    A true P0 should reflect measurable business loss, like a bug letting users use services for free.

    A crash affecting 10 users out of 30 million? That’s a P2. It’s annoying, sure, but it’s not urgent.

  3. Set Realistic Expectations for Each Priority Level

    Use volume thresholds per environment:

    • Prod: Max 1 P0/week, 1 P1/day. The rest should be P2+.

    • This helps you track the system’s health over time.

      If your system doesn't match the production schema, it's a broken system that needs to have full capacity to fix it, not to bring more features (and bugs) to it.

  4. Treat Long Fixes as Tasks, Not Alerts

    If a "bug fix" takes the entire on-call week, it's not a bug — it's a feature request or tech debt task. Don’t let it sit in your incident queue.

The goal is to build a system where alarms are actionable, meaningful, and matched to business priorities — not just noise that trains people to ignore real problems.

Having a better alarm system will boost the on-call experience, bring tech debt under control, and make fixing incidents way faster.

Thursday, 2 January 2025

The Power of MVP

Every groundbreaking app begins with a question: How can we turn this idea into a reality that delivers maximum impact while minimizing resources and effort? Enter the MVP—a powerful strategy that not only tests your concept in the real world but also paves the way for rapid growth and innovation. But what makes an MVP so transformative? Let’s find out.

What is MVP?

MVP stands for "minimum viable product." It's a common term in the software development industry. An MVP is defined as a product with just enough features to allow users to start using it, while deferring non-essential functionalities for later. Everything non-essential is deferred to later, provided user satisfaction remains intact.

Before diving deeper into the definition, let's understand the problem that MVP aims to solve.

Challenges MVP Seeks to Address

There are countless ideas for new products in the software development world. However, before investing resources, every idea must pass through two critical validations:

  1. Technology Validation: Can this idea be implemented? This involves determining if the software development world can deliver a solution that optimizes time, operating costs, and money while identifying potential limitations and operational expenses.

  2. Market Validation: Is there a demand for this product? This means analyzing whether customers will pay for the product, even if they need it. The rule here is: "A customer’s need for a product doesn’t always translate into a willingness to pay for it." Some users might not engage unless it fits their price expectations or operational benefits. Companies must evaluate the business model carefully.

Neither of these questions has quick answers. They require research, prototypes, and sample data for clarity. However, the challenge arises when a project incurs high costs due to months of work by engineers, server expenses, project management, design, marketing, and more—only to discover that the product isn’t valuable.

While technology validation can often be addressed through research, market validation usually requires real-world data and feedback. Most products, especially in their early stages, struggle with obtaining direct user feedback or indirect feedback through market responses. This is where the MVP approach proves invaluable by allowing teams to test ideas with minimal investment and gather essential feedback early.

MVP as a Solution

MVP focuses on reducing development and operational costs, enabling teams to validate a product’s value before committing extensive resources. That said, reducing costs excessively can shift the focus from product issues to resource issues.

One reason the MVP concept is so popular is its compatibility with agile methodologies. Agile emphasizes delivering incremental improvements in short cycles and responding to feedback quickly. As a result, MVPs are easier to integrate into workflows when teams are familiar with agile principles.

Take Uber, for example: It started with basic features and gradually evolved into a platform offering diverse ride options across many countries.

How to Use MVP?

The most critical and challenging part of an MVP is minimizing costs while keeping the product viable. There are many differing opinions on which features to prioritize and which to push for later. For example, a user-friendly UI often sparks debate. Some argue that a functional UI is sufficient and doesn’t impact the main experience. Others contend that poor UI design, particularly for new users, can significantly reduce retention rates.

Perhaps the right question here is: What are the critical factors that will make users abandon the app?

  • Define the core features of the product to make it easier to eliminate "nice-to-have" features.
  • Consider the type of target audience. For instance, certain user segments prioritize security, UI, or privacy. If they are your target users, then features addressing their priorities should take precedence.

MVP vs Demo

While they may seem similar, there is a significant difference between an MVP and a demo. A demo is an incomplete project used only to present an overview of the final product. It is normal for a demo to have bugs and optimization issues.

An MVP, on the other hand, is a complete product with very limited functionality (ideally focused on a single feature) but capable of improvement. In practice, confusing these terms can lead to unrealistic expectations, such as assuming an MVP will demonstrate all features, even if they are not functional yet.

Can MVP Be Bad?

One downside to MVPs is that they often prioritize quick results over everything else, which can lead teams to adopt bad practices. Examples include poor architecture, bad code, lack of tests, secrets stored in code or text files, databases stored in text files, and a reliance on manual deployment processes.

Many justify these choices by saying, "We know it’s wrong, but we’ll fix it later." However, this mindset can create two significant issues:

  1. Bad Practices Become Ingrained: These shortcuts often become part of the product’s core. New features may also inherit these bad practices.
  2. The Pain of Migration: Most of the time, migration never happens. Once the product “works,” no one will care about the pain caused by fixing bugs in messy, complex code—except the engineers tasked with doing so.

When Should You Avoid MVP?

Certain projects may not benefit from an MVP approach. For example, in industries where users expect a full experience from the start, launching an underdeveloped product can harm your brand.

One notable example is a dessert company in Egypt that launched an app. Despite heavy marketing investment, the app suffered from significant usability issues, including long login times, sluggish navigation, and inaccurate product availability.

Conclusion

MVP is a powerful approach when combined with an agile environment, as long as teams stick to its principles. Teams must avoid overbuilding for future needs while ensuring that the MVP approach doesn’t justify poor development practices. By focusing on quality and core functionality, companies can leverage MVP effectively without compromising their long-term success.

Saturday, 5 October 2024

Choosing Between Relational, Document, and Graph Models

Choosing the right database is one of the most critical decisions in system architecture. Whether you're dealing with structured or unstructured data, normalized or denormalized data, the choice you make will affect your system's scalability, performance, and maintainability.

This article aims to guide you through the differences between relational, document, and graph databases—highlighting when each type is most suitable, the challenges of using them together in a single system, and key factors to consider for making the best decision for your use case. We'll also explore whether it's feasible for a system to incorporate multiple database types and discuss potential pitfalls of such an approach. By the end, you'll be better equipped to select a database strategy that aligns with your business needs and technical requirements.

Choosing Between Relational and Document Databases

When choosing the right database for your system, it's important to first understand your business needs and use cases. Know the access patterns, the type of data you're storing, and how the business plans to utilize that data.

A common but overly simplistic guideline is: if you have structured data, use a relational database; if it's unstructured, use a document database. However, this approach is misleading. In reality, unstructured data can be stored in a relational database, and structured data can also be efficiently stored in a document database. The choice is less about structure and more about how the data is used and how relationships between data are managed.

Here are some key questions to help guide your decision:

  • Do you need to query on multiple fields frequently?
  • Do you often need to access full records in a single query?
  • What kinds of relationships exist between different records or tables?
  • Does your business require frequent locks and transactions?
  • Does your data have a natural grouping, or does it vary significantly from record to record?
  • How complex are the relationships between your data points?

From my experience, there's a general rule: don't use a relational database without a strong reason. Relational databases provide a lot of power, including support for locks, transactions, relationships, and constraints in a native way. While some document databases offer these features, they often come with trade-offs, like added complexity or performance penalties.

On the other hand, choosing a document database without fully understanding your access patterns could lead to challenges like:

  • Frequent Full Table Scans: Without appropriate understanding of query patterns, you may end up scanning entire collections frequently, increasing costs.
  • Data Consistency Issues: Ensuring data consistency, like unique constraints across collections, can be complex in a document database.
  • Data Duplication: To support access patterns, you might end up duplicating data across collections, leading to the headache of keeping that data in sync.

Understanding Graph Databases

Graph databases can be thought of as a specialized type of document database, but with a focus on modeling relationships. They were created to solve performance issues related to complex relationships in relational databases by storing data as a network of entities and relationships. This type of structure allows graph databases to efficiently handle use cases with a lot of interconnected data.

A graph database uses graph theory to model and perform operations on data relationships, making it an excellent choice for scenarios where relationships are central to the data model. Some natural use cases include:

  • Social Networks: Representing people and the relationships between them.
  • Fraud Detection: Identifying suspicious patterns based on connected entities.
  • Network Management: Modeling and analyzing computer networks.

While I haven’t used graph databases in practice—my knowledge is mostly theoretical—it's clear that they can significantly improve performance when dealing with complex and numerous relationships.

Can a System Use Multiple Types of Databases?

Using two different types of databases in the same system comes with several challenges.

In a microservices architecture, it is sometimes argued that if a service requires multiple databases, it could be split into two separate services, each with its own database. This kind of approach aligns with the single responsibility principle and allows each service to scale independently, using the best database for its specific needs.

However, in a monolithic system, using multiple databases can introduce complications:

  • It gives developers too much flexibility, pushing design decisions into implementation. This means developers will have to constantly make choices like "Which database should I use for this case?"—a decision that should ideally be made during design, not development.
  • It reduces isolation between the business layer and the database layer, since the business logic becomes aware of specific implementation details across multiple databases.

While I've seen systems that use multiple databases simultaneously, I've also seen ways to avoid this approach. There may be use cases where this is justifiable, although I haven't encountered or thought of them all. One potential reason for using multiple databases is cost reduction—specifically, when there is a need to lower operational costs, but the resources required to migrate to a better-architected system are not available. In such cases, maintaining an old database while integrating a new one may seem like a practical, albeit temporary, solution.

Final Advice

The decision of which database to use is not one to take lightly. It requires a deep understanding of your application's needs, the nature of your data, and how you intend to scale. Relational, document, and graph databases each have their strengths and limitations, and selecting the right one can significantly impact your system's performance and maintainability.

Migrating from one database model to another can be a time-consuming and challenging process, especially when large volumes of data are involved. It’s best to thoroughly evaluate your needs and validate your decision before committing to a database model.

Conclusion

Choosing the right database is not a one-size-fits-all decision. Each type of database has its unique strengths, and understanding your business requirements and technical constraints is key to making the right choice. It’s also crucial to understand the challenges of using multiple database types within a single system, as doing so can add unnecessary complexity and impact maintainability.

In the next articles, we'll dive deeper into some common challenges: Why does a current database have poor performance, and how can we fix it? We'll also explore the differences between popular database management tools—comparing MySQL to MS SQL, and DynamoDB to Cosmos DB.

Technical Design Document

In software development, we often move fast—especially in agile environments. But moving fast doesn’t mean skipping structure. One of the mo...