Tag: Client Management

  • Case study 19: When Code Breaks a Client’s Website: How Programmers Should Communicate During a Production Incident

    The code failed. The communication shouldn’t.

    Every programmer eventually makes a mistake.

    Sometimes it is a small bug that affects one button. Sometimes it is a database query that returns the wrong result. And sometimes, especially when working directly on a live website, a mistake can make an entire website appear broken.

    For a programmer, the technical problem may be understandable: a misplaced function, a bad configuration, an unexpected server response, or a plugin conflict.

    For the client, however, the situation is very different.

    They may see a blank website.

    They may be unable to access WordPress administration.

    They may worry that their data is gone.

    They may wonder whether their business is losing customers.

    And they may immediately ask:

    “What happened?”

    At that moment, technical ability is only half of the job.

    The other half is communication.

    A lesson from a real freelance project

    Early in my freelance work, I experienced a situation that taught me an important lesson about communicating during technical incidents.

    A client hired me to develop a WordPress plugin that would generate an XML feed from their website and synchronize advertisements with another property platform.

    The project was relatively small. The agreed price was $30, with a three-day delivery period and source code included.

    While developing the plugin, I made a mistake in the code. An exit() statement had been placed incorrectly.

    The result was serious: the client’s live WordPress website became inaccessible.

    The client reported that the website was blank and that even the WordPress administration area was not working correctly.

    Naturally, the client’s reaction was emotional.

    From the developer’s perspective, the underlying problem was identifiable and potentially recoverable. From the client’s perspective, however, their website was down.

    That distinction is extremely important.

    Technical reality and client reality are different

    A programmer might think:

    “The plugin is causing the problem. We simply need to disable it.”

    The client might think:

    “My website has disappeared. Is my data safe? Is my business website destroyed? Who is going to pay for this?”

    Both perspectives are understandable.

    The programmer sees the cause.

    The client sees the impact.

    Good communication connects those two perspectives.

    One of the messages I sent at the time was essentially:

    “Your website is ok, we need to remove the plugin.”

    Technically, I was trying to reassure the client.

    But looking back, that was not the best wording.

    If the client is looking at a blank website, telling them that the website is “OK” can sound as though the developer is denying the problem.

    A better approach would have been:

    “I understand that the website is currently blank. I have identified the plugin as the cause. The website files and content should still be intact, and the immediate step is to disable the plugin so we can restore normal access.”

    That message does several things:

    • acknowledges the visible problem;
    • takes responsibility;
    • explains what has been identified;
    • reduces unnecessary panic;
    • provides a recovery direction.

    That is much more effective communication.

    The Five-Step Incident Communication Framework

    When your code causes a problem on a client’s live system, use this simple framework:

    Acknowledge → Own → Explain → Recover → Prevent

    Let’s examine each step.

    1. Acknowledge the problem

    Start with what the client is experiencing.

    Don’t immediately start talking about PHP functions, WordPress hooks, database queries, server configuration, or XML.

    Say:

    “I understand that the website is currently showing a blank page.”

    This confirms that you understand the problem.

    It also prevents the client from feeling ignored.

    During an incident, the first communication should answer:

    “Do you understand what is happening?”

    Only after that should you move into technical details.


    2. Own the mistake

    If your code caused the problem, say so clearly.

    Avoid language such as:

    • “Something happened.”
    • “The server is acting strange.”
    • “Maybe HostGator caused it.”
    • “WordPress is having an issue.”
    • “It could be a plugin conflict.”

    If you already know your code is responsible, don’t hide behind uncertainty.

    A professional message is:

    “I found an issue in the plugin code that is causing the website to stop loading. This is my mistake, and I will focus first on restoring the website.”

    Taking responsibility does not make you look weak.

    In fact, it often establishes trust.

    Clients generally understand that programmers can make mistakes. What damages confidence is when the programmer appears to avoid responsibility.


    3. Explain the technical cause — but in the right amount

    Once the immediate situation is acknowledged, explain the cause.

    In this case, the issue involved an incorrectly placed exit() function inside a new WordPress plugin.

    A technical explanation could be:

    “The plugin contains an exit() call in the wrong execution path. Because the plugin is loaded by WordPress, the statement interrupts normal page execution and results in the blank page.”

    That is useful.

    But the explanation should not become a lecture.

    The client usually doesn’t need to understand PHP execution flow while their website is unavailable.

    Think about the difference between these two messages:

    Too technical:

    “The exit() function is terminating execution before WordPress completes the template lifecycle, probably because the hook is being executed globally.”

    Better:

    “I found an error in the new plugin that stops WordPress from completing the page request. I know where the problem is and am working on disabling the affected component first.”

    The second message communicates the same essential information without overwhelming the client.


    4. Give a recovery plan

    This is perhaps the most important part.

    When a website is down, don’t send ten possible solutions.

    Give the client a clear sequence.

    For example:

    Step 1: Disable the affected plugin.

    Step 2: Confirm that the website loads again.

    Step 3: Inspect and correct the plugin code.

    Step 4: Test the corrected plugin on a safe environment.

    Step 5: Only then reinstall or reactivate it on the live website.

    This is much better than sending a series of disconnected instructions.

    During a production incident, the client wants to know:

    “What happens next?”

    Answer that question explicitly.


    5. Explain how you will prevent a repeat

    After the website is restored, don’t simply say:

    “Fixed.”

    Explain what changed.

    For example:

    “The plugin has been corrected and tested separately. I have also removed the execution path that caused the page to stop loading. Before reactivating it on the live website, I will test the feed generation and WordPress admin functionality.”

    This demonstrates that you are not merely patching the symptom.

    You are addressing the underlying problem.

    Don’t make the client troubleshoot your code

    One of the lessons I learned from this experience is that developers should be careful about transferring technical responsibility to the client during an incident.

    Asking a client to:

    “Remove this folder from wp-content/plugins/”

    may be technically valid.

    But if the client isn’t a developer, they may not be comfortable working inside the hosting filesystem.

    A better approach is to explain why the action is needed:

    “The problem is isolated to the new domaza_xml_feed plugin. Temporarily disabling that plugin should allow WordPress to load normally. If you can provide temporary FTP or hosting access, I can perform the change myself.”

    This is much more reassuring.

    The client understands:

    • what is being changed;
    • why it is being changed;
    • what the expected result is;
    • and who is responsible for the fix.

    Avoid promises like “I’ll fix it in no time”

    When a website is down, developers sometimes try to reassure clients with statements such as:

    “I will fix it in no time.”

    The intention is good.

    The problem is that it creates an unnecessary promise.

    What if the hosting environment introduces another issue?

    What if the backup is unavailable?

    What if the problem is more complicated than initially expected?

    Instead, communicate the next concrete action:

    “My first priority is to restore the website. I will disable the affected plugin and then investigate the code separately.”

    That is confident without making an unrealistic guarantee.

    Never send ten messages when one clear message will do

    Another common mistake during stressful situations is sending message after message.

    For example:

    “Please share hosting access.”

    Then:

    “FTP access would be better.”

    Then:

    “Please ask your hosting provider.”

    Then:

    “Please disable the plugin.”

    Then:

    “Give me one chance.”

    The developer may be trying to help, but to the client it can look like uncertainty.

    A better communication pattern is:

    What happened → What I found → What I will do → What I need from you.

    For example:

    “I identified the new plugin as the cause of the blank page. The issue is related to an execution statement in the plugin code. I need to disable the plugin first to restore the website. If you can provide temporary FTP access, I can do this directly; otherwise, your hosting provider can disable the plugin using the plugin folder name domaza_xml_feed.”

    One message.

    Clear.

    Actionable.

    Professional.

    What about an angry client?

    Clients may write in capital letters.

    They may ask:

    “WHAT DID YOU DO?”

    They may ask:

    “WHO WILL PAY ME?”

    They may blame the developer.

    Your response should not mirror their emotional tone.

    Don’t argue.

    Don’t write:

    “Calm down.”

    Don’t say:

    “It’s not a big problem.”

    Don’t immediately defend yourself.

    Instead:

    “I understand why you’re concerned. The website is currently affected by the plugin I was developing, and I take responsibility for correcting the issue. My immediate priority is to restore the website.”

    This changes the conversation from blame to resolution.

    The importance of testing before touching production

    There is also a technical lesson behind the communication lesson.

    If you are developing a WordPress plugin that can affect the entire website, avoid treating the client’s live website as your development environment whenever possible.

    A safer workflow is:

    Development → Staging → Testing → Backup → Production

    Before activating a new plugin on production:

    • take a backup;
    • test the plugin on staging;
    • verify WordPress admin access;
    • test the homepage;
    • test important custom post types;
    • test database operations;
    • test feed generation;
    • check PHP errors;
    • verify that disabling the plugin restores normal operation.

    For small freelance projects, you may not always have a complete staging environment.

    But you can still create a safer process.

    Even a local WordPress installation or temporary test environment is better than experimenting directly on a client’s live business website.

    Communication is part of programming

    A common misconception among new programmers is that their job is simply to write working code.

    It isn’t.

    Professional software development also involves:

    • understanding requirements;
    • setting expectations;
    • documenting changes;
    • communicating risks;
    • reporting progress;
    • handling failures;
    • explaining technical decisions;
    • and taking responsibility when something goes wrong.

    A developer who writes excellent code but communicates poorly can still create a poor client experience.

    Likewise, a developer who makes an occasional mistake but communicates clearly, takes responsibility, and fixes the problem professionally can maintain a strong working relationship.

    The goal isn’t to become a programmer who never makes mistakes.

    The goal is to become a programmer who knows how to respond when mistakes happen.

    A practical emergency message template

    New programmers and freelancers can keep a template like this available:

    Hi [Client Name],

    I understand that the website is currently affected, and I have identified the issue as coming from the code I recently added.

    I take responsibility for the problem. My first priority is to restore the website, so I recommend temporarily disabling the affected component.

    Once the website is back online, I will investigate and correct the code separately and test the fix before activating it again.

    If you can provide temporary [FTP/hosting/staging] access, I can handle the recovery directly.

    I will keep you updated on the progress and explain the final cause and fix once the issue is resolved.

    Regards,
    [Your Name]

    The template can be adapted depending on the situation.

    The important part is the structure, not the exact wording.

    Five rules every new programmer should remember

    When your code causes a production problem:

    1. Don’t hide the mistake.
    If your code caused it, acknowledge it.

    2. Don’t overwhelm the client with technical details.
    Explain the cause at the level necessary to understand the situation.

    3. Don’t argue about whether the problem is “serious.”
    Focus on restoring the service.

    4. Don’t give multiple conflicting instructions.
    Give one clear recovery plan.

    5. Don’t stop communicating after the fix.
    Explain what happened, what you changed, and how you will reduce the chance of recurrence.

    The bigger lesson

    That 2023 WordPress project was not an example of perfect development.

    It was an example of something more useful: learning from a real production mistake.

    The technical mistake was relatively simple.

    The larger lesson was about professional responsibility.

    When a developer’s code affects a client’s website, the client doesn’t need a perfect programmer.

    They need a programmer who is:

    honest, calm, clear, accountable, and focused on recovery.

    Years of programming experience teach you that bugs are unavoidable.

    Professionalism is demonstrated by what you do next.

    The best developers don’t communicate only when everything works.

    They communicate especially well when something doesn’t work.

    And sometimes, the most valuable lesson from a broken website isn’t found in the code.

    It is found in the conversation that follows.

  • How a Client Got a Full Refund Six Months After an Order Was Completed — And What I Learned

    As a freelancer, one of the hardest lessons to learn is that finishing a project does not always mean the project is truly finished.

    I recently experienced a situation where a client received a completed project, the order was accepted, and the original scope had effectively been delivered. Months later, however, the client requested significant changes to the project.

    What followed eventually resulted in a full refund of the original order amount — approximately six months after the order had been completed.

    This experience changed the way I think about project scope, revisions, acceptance, documentation, and what freelancers should do when a client wants to fundamentally change an already completed project.

    The project was completed

    The project originally had a defined scope and price.

    I completed the work according to that scope, delivered the agreed functionality, and the client accepted the order.

    At that point, from a normal freelance-project perspective, the transaction should have been closed.

    The important lesson here is that an accepted order creates a psychological sense of finality, but freelancers should not assume that the risk has completely disappeared.

    I now believe that completion and acceptance are only one part of protecting yourself.

    The other part is maintaining a clear record of:

    • What was originally requested
    • What was actually delivered
    • What the client approved
    • What revisions were included
    • What changed later
    • When those changes were requested
    • Whether the new request materially changed the architecture or workload

    Then the requirements changed

    Several months after the original order was completed, the client requested a major change.

    This was not simply a small correction or a minor bug fix.

    The requested change affected the underlying way the system obtained and processed its data.

    Initially, I treated the request as a goodwill gesture rather than immediately treating it as a completely new project.

    That decision is something I have thought about a lot since then.

    As a freelancer, it is natural to want to help a long-term client.

    You think:

    “I already know the project. I’ll take care of this small change.”

    The problem is that something that looks small from the client’s perspective can become a completely different engineering problem.

    A change in the data source, architecture, workflow, validation requirements, or external dependencies can have consequences throughout the entire system.

    What starts as “just change the source” can become:

    new ingestion → new parsing → new normalization → new caching → new testing → new diagnostics → new failure handling → new documentation → new acceptance criteria.

    At that point, it is no longer simply a revision.

    It is a new engineering phase.

    The hidden cost of saying “I’ll do it for free”

    This was probably the biggest lesson for me.

    When I agreed to look into the change without immediately charging a new project fee, I intended to provide good customer service.

    Instead, I gradually became responsible for work that was significantly larger than the original request.

    The more I investigated the new requirements, the more complexity became visible.

    There were new technical questions, testing requirements, external-source issues, diagnostics, caching considerations, and additional acceptance expectations.

    The amount of engineering effort grew substantially.

    And this created an uncomfortable situation:

    The client viewed the work as a continuation of the original project.

    I increasingly viewed it as a materially different project.

    That difference in perception is dangerous.

    The most important lesson: define “change” before doing it

    A freelancer should not ask only:

    “Can I technically make this change?”

    The more important question is:

    “Does this change remain inside the original commercial scope?”

    Those are two completely different questions.

    A technically possible change can still be commercially outside the original agreement.

    For example, these may look like minor requests:

    • “Use another source.”
    • “Change the input format.”
    • “Add another validation layer.”
    • “Make it work with this external service.”
    • “Add comprehensive unit testing.”
    • “Add diagnostics.”
    • “Provide evidence for every component.”
    • “Change the architecture.”

    But each can potentially create substantial additional work.

    The freelancer has to identify that boundary early.

    Six months changes the situation — but does not eliminate risk

    One of the most surprising parts of this experience was the timing.

    The original order had been completed approximately six months earlier.

    From the freelancer’s perspective, the project was old.

    From the client’s perspective, however, the client was still looking at the overall project and raising concerns about what they believed remained incomplete.

    That taught me something important:

    Time alone does not protect a freelancer from a scope dispute. Documentation does.

    A freelancer should be able to open the project history months later and immediately demonstrate:

    1. What the original agreement said.
    2. What was delivered.
    3. What the client accepted.
    4. What changed afterward.
    5. Why the later request required additional work.

    Without that record, a dispute can become a matter of interpretation.

    The full refund was the hardest lesson

    Eventually, the situation resulted in a full refund of the original order amount.

    For a freelancer, this is more than simply losing the money.

    There is also the opportunity cost.

    The time spent investigating, developing, testing, documenting, communicating, and trying to resolve the dispute cannot be recovered.

    And if substantial unpaid work has been performed after the original order, the freelancer can end up in an especially difficult position:

    The original project has already been delivered, but the freelancer has also invested significant additional time trying to accommodate a later change — and ultimately receives nothing for either phase.

    That is an extremely expensive lesson.

    What I would do differently now

    If I faced the same situation again, I would handle it differently.

    1. Freeze the original scope

    Once an order is completed and accepted, I would clearly distinguish between:

    Original scope

    and

    New requested work.

    I would not automatically assume that a later request is a revision.

    2. Perform a change-impact assessment

    Before writing code, I would explain:

    “I can investigate this change, but first I need to determine whether it can be implemented within the existing architecture and scope.”

    That small sentence can prevent a major misunderstanding.

    3. Separate investigation from implementation

    Investigation itself can require significant engineering time.

    A better process is:

    Phase 1 — Assessment

    Determine feasibility, architecture impact, estimated effort, risks and dependencies.

    Phase 2 — Proposal

    Provide a separate price and timeline.

    Phase 3 — Implementation

    Begin development only after the new scope is approved.

    This prevents “free investigation” from quietly turning into months of unpaid development.

    4. Never rely on goodwill as a substitute for scope

    Goodwill is valuable.

    But goodwill should have boundaries.

    A freelancer can say:

    “I’ll take a quick look at this as a courtesy.”

    But that should not automatically become:

    “I’ll rebuild the system around this new requirement for free.”

    5. Put material changes in writing

    If the client changes an important requirement, document it explicitly.

    For example:

    “The original implementation used Source A. You are now requesting Source B. This changes the ingestion architecture and therefore requires additional development.”

    That single statement establishes a written record of the change.

    6. Don’t let sunk costs dictate the next decision

    Another trap is thinking:

    “I’ve already spent 30 hours on this, so I should keep going.”

    That can become:

    30 hours → 50 hours → 80 hours → 100 hours.

    At some point, continuing is no longer protecting the original investment.

    It is increasing the loss.

    A better question is:

    “If I had not already spent any time on this, would I agree to take on this new scope for the current price?”

    If the answer is no, stop and renegotiate.

    What clients can learn from this too

    This is not only a freelancer lesson.

    Clients also benefit from clearly separating:

    bug fixes,
    revisions, and
    new requirements.

    A freelancer should not be expected to absorb an architectural change simply because the change relates to the same product.

    If the underlying requirement changes, the commercial agreement may need to change as well.

    That is not necessarily a sign of a difficult freelancer.

    It is often simply good project management.

    The real lesson

    The biggest lesson I took from this experience is not:

    “Never help a client.”

    It is:

    “Help clients, but never allow goodwill to replace a clearly defined scope.”

    I still believe that good freelancers should be flexible.

    Sometimes you should fix something without charging.

    Sometimes you should help a client with a small change.

    Sometimes you should go beyond the written requirements because building a good relationship matters.

    But there needs to be a clear boundary between customer service and taking responsibility for an entirely new project.

    When that boundary disappears, everyone can end up with a different understanding of what was agreed.

    And when that disagreement surfaces months later, the freelancer may discover that the cost of being generous was much higher than expected.

    My advice to other freelancers

    If you are a freelancer, especially if you work on custom software or development projects, I would strongly recommend keeping a simple project record containing:

    • Original scope
    • Original price
    • Delivery date
    • Acceptance date
    • Client approvals
    • Revision history
    • New requirements
    • Change requests
    • Additional estimates
    • Additional approvals
    • Major technical decisions
    • Final delivery evidence

    And perhaps most importantly:

    Do not start substantial work on a materially different requirement simply because you want to be helpful.

    First determine what changed.

    Then determine what it will take.

    Then agree on the new scope.

    Then start.

    Because sometimes the most expensive sentence a freelancer can say is:

    “Don’t worry, I’ll do this one for free.”