9 habits that make you leak your personal data

In the digital age, personal data is an extremely valuable asset. However, many people unintentionally expose their own information due to habits that seem harmless. Below are common habits that make you vulnerable to data theft—and that you should stop immediately.

1. Using Weak or Reused Passwords

This is the most common mistake in personal security. In many data breach cases, users were found using extremely simple passwords like “123456” or “password”. Others create passwords based on personal information, making them easy to guess.

There are many tools in cybersecurity designed to guess passwords using personal data by trying all possible combinations—this technique is known as brute force.

In addition, reusing the same password across multiple platforms makes things much worse. If one account is compromised, all others are at risk.

Best practice:

  • Use passwords with at least 10 characters
  • Avoid personal information
  • Combine letters, numbers, and special characters

2. Saving Passwords in Browsers

Browsers like Chrome and Firefox offer password-saving features for convenience. However, this habit carries risks.

If these browsers have undiscovered vulnerabilities (known as zero-day vulnerabilities), attackers could potentially steal stored passwords.

Also, when using shared computers—such as in internet cafés, print shops, or even your workplace—you should never save passwords. Others may access your accounts through stored credentials.

Safer alternatives:

  • Memorize important passwords
  • Use encrypted password managers with biometric authentication
  • Always log out after use, especially on shared devices

3. Connecting to Unsafe Public Wi-Fi

Free Wi-Fi at cafés or airports is often poorly secured.

Common risks include:

  • Weak encryption:
    If a network uses WEP or WPA, avoid connecting. These encryption methods are outdated and easily cracked.
    The minimum safe standard today is WPA2 or higher (as of 2026).
  • Evil Twin attacks:
    Attackers create fake Wi-Fi networks with the same name as legitimate ones. If you connect, they can monitor your activity or steal login data.
  • Unnecessary data collection:
    Some Wi-Fi networks request personal information through surveys—you can usually skip this step.

4. Clicking on Suspicious Links (Phishing)

Phishing is one of the most common ways attackers steal data. It relies on psychological manipulation to trick users into revealing information or installing malware.

Common phishing scenarios:

  • Fake banking emails that tell your account has some problems.
  • “You’ve won a prize” messages
  • Fake login pages of others popular websites

To avoid be fooled, you must always double check the domain name on the url. A simple trick is you should search the business name on google and call their customer support to confirm situation.


5. Installing Apps from Untrusted Sources

Applications downloaded from unofficial sources may contain malware designed to steal data.

Attackers often disguise malware as:

  • Free “useful” software
  • Cracked versions of paid tools

Trusting unknown sources can lead to data theft or even ransomware.

Stay safe by:

  • Downloading software only from official websites
  • Verifying sources before installing

6. Oversharing on Social Media

People today spend more time on social media platforms like Facebook, TikTok, and X than in real life.

Sharing too much personal information can be dangerous. Scammers can collect:

  • Your name and location
  • Friends and family connections
  • Habits and interests

This information can be used for scams, impersonation, or malware attacks.

Even more concerning, modern AI can generate fake images or sensitive videos using just a few photos of your face.

Protect yourself by:

  • Limiting personal information shared online
  • Avoiding posting sensitive content
  • Enabling profile privacy settings

7. Not Enabling Two-Factor Authentication (2FA)

Many popular platforms like Gmail, Facebook, and X offer two-factor authentication (2FA).

This feature adds an extra layer of security by requiring:

  • OTP codes sent to your phone
  • Biometric verification

Even if your password is compromised, attackers still cannot fully access your account.

However, 2FA is often disabled by default.

Action step:
Review your accounts and enable 2FA as soon as possible.


8. Not Updating Software & Using Cracked Versions

Outdated software often contains serious unpatched vulnerabilities that attackers can exploit.

Many people think updates are only for:

  • New features
  • Better UI
  • Performance improvements

But the most important purpose is security patching.

Each update typically:

  • Fixes known vulnerabilities
  • Blocks new attack methods
  • Strengthens system defenses

Without updates, you may be using software with publicly known exploits.

In some cases, simply opening a malicious image, audio file, or website can infect your system through these vulnerabilities.

Best practice:

  • Always update to the latest version
  • Avoid cracked software—they may include hidden malware

9. Ignoring App Permissions

Many apps collect more data than necessary, but users often ignore this.

On app stores, applications must declare required permissions—but most users simply tap “Allow” without review.

This habit may result in:

  • Sharing personal data unnecessarily
  • Giving apps access to sensitive system features

Stay in control by:

  • Reviewing permissions before installing
  • Avoiding apps with excessive or unrelated access requests
  • Checking reviews or consulting experts if unsure

Conclusion

The habits that lead to personal data exposure are often small—but the long-term consequences can be severe.

By recognizing and correcting these behaviors, you can significantly improve your cybersecurity awareness and avoid unnecessary risks on the Internet.

7 risks on Internet that You must know

A normal morning.

You wake up, check your phone, read emails, scroll through social media, and pay a few bills. Everything feels fast, familiar—almost automatic.

But within those “normal” moments, countless hidden risks quietly exist in the digital world.

Cyberattacks are not always loud or obvious. Sometimes, they begin with a careless click, a rushed login, or a misplaced trust.

Below are familiar scenarios—each representing some of the most common threats on the internet today that you could encounter at any time.


1. Phishing (Impersonation Scams)

You receive an email from your “bank” warning about suspicious activity. The message looks professional, complete with logos and branding, and includes a link asking you to log in immediately to verify your account.

Feeling concerned, you click the link and enter your information. Everything seems normal… until a few hours later, your account is compromised.

Common signs of phishing:

  • Urgent, well-written emails that mimic official communication
  • Fake login websites that look almost identical to real ones
  • Suspicious domain names (typos, mismatched names, or strange subdomains)

This method exploits users who are unfamiliar with how domains and links work.

If you’re not confident in identifying suspicious links, consider using tools like SafePhone, which can detect and block phishing links before you even access them.


2. Malware (Malicious Software)

You download a free tool online because it “looks useful.” Installation is quick and smooth—nothing seems wrong.

But soon after, your device becomes slower, and your data may be accessed without your knowledge.

This could be malware—software designed to secretly monitor or steal your information.

Common sources:

  • Email attachments
  • Downloads from forums or unknown websites
  • Cracked or pirated software

How to stay safe:

  • Only download apps from trusted platforms like official app stores
  • Install reliable antivirus software
  • Avoid unknown or suspicious files

3. Ransomware (Data Extortion Malware)

One day, you turn on your computer—and all your files are locked. A message appears demanding payment to restore access.

No warning. No undo.

This is ransomware, one of the most serious cyber threats today.

Once inside your system, it will:

  • Encrypt all your data
  • Demand payment for a decryption key
  • Often require payment in cryptocurrencies like Bitcoin or Ethereum to avoid traceability

Prevention tips:

  • Only install software from official sources
  • Use updated antivirus protection
  • Regularly back up your data

4. Online Scams

A friend messages you on social media, saying they’re in urgent need of money. The message feels real—the tone is familiar. Without hesitation, you transfer the money.

Later, you find out their account was hacked.

Common scam patterns:

  • Impersonating friends by copying profile pictures and information
  • Fake investment opportunities
  • Requesting deposits and then disappearing
  • Trick you into installing malware
  • Using your identity to scam others

How to protect yourself:

  • Lock your social media profiles
  • Be cautious with financial requests
  • Verify identity via video calls
  • Use shared private memories to confirm authenticity

5. Data Breaches

You reuse the same email and password across multiple services. One day, you receive a notification about a login from an unknown device.

It’s not necessarily your mistake—one of the services you used may have been breached.

Your data could have been exposed long ago and is now circulating on underground markets.

Risks include:

  • Compromised login credentials
  • Personal data leaks
  • Chain attacks across multiple accounts
  • Financial loss

Reduce risk by:

  • Using unique passwords for each service
  • Changing passwords regularly
  • Using encrypted password managers with biometric protection

6. Public Wi-Fi Attacks

You sit at a café and connect to free Wi-Fi. It’s convenient and fast.

But at the same time, someone could be monitoring your data.

Risks of public Wi-Fi:

  • Data interception if encryption is weak
  • Fake Wi-Fi networks (Evil Twin attacks)
  • Unauthorized access to your device

7. Social Engineering (Psychological Manipulation)

You receive a call from “technical support” asking for an OTP code to “verify your account.” They sound professional, trustworthy—even urgent.

In reality, they are not hacking systems—they are hacking you.

Common tactics:

  • Impersonating authorities
  • Creating urgent scenarios (accidents, penalties, account suspension)
  • Pretending to be someone you trust

Conclusion

The digital world isn’t dangerous in obvious ways—it’s dangerous because threats often appear in familiar forms.

An email. A message. An app.
Each could be the starting point of a serious incident.

Understanding these risks doesn’t just help you avoid them—it helps you make better decisions in moments that seem completely ordinary.

6 entrances that hackers use to infiltrate your company

If you are a business owner, you are likely no stranger to news about data breaches causing millions of dollars in losses across companies in all industries. The leaked data could be your customers’ information, and sometimes even employee login credentials for your internal systems. Regardless of the type of data, assessing and reviewing vulnerabilities is always a critical step for every company—especially in today’s digital era.

However, security vulnerabilities are an extremely complex concept and not easy to grasp, which makes them difficult for business owners and their teams to identify. While it is hard to pinpoint exact vulnerabilities, it is much easier to block the sources that commonly lead to them. Therefore, this article will highlight several common sources of serious security vulnerabilities and suggest solutions to strengthen security for you, your company, and anyone working in the modern digital age.

1. Outdated Software

Every business today uses various software tools to automate and optimize workflows—such as Chrome, Word, Excel, Photoshop, PDF readers, and many specialized tools. These software products are developed by different developers, who may or may not have strong expertise in security. As a result, features may contain vulnerabilities that even the creators are unaware of.

Software is constantly updated, and many updates include patches for bugs and security flaws. However, most people tend to stick with older versions or hesitate to update—sometimes simply because they are unaware of new releases. This habit can leave systems exposed to unpatched vulnerabilities, making them easy targets for hackers.

Information about known vulnerabilities can even be bought and sold on black markets, including the dark web and deep web. This makes outdated software a highly attractive entry point for attackers. Therefore, always keep your software up to date to reduce security risks.


2. Outdated Windows Operating System

Older Windows versions such as Windows 7, Windows XP, or unsupported Windows Server editions are prime targets for hackers. This is because Windows itself is a collection of system-level software components, many of which may contain unpatched vulnerabilities over time.

Taking advantage of users’ reluctance to upgrade, many hacking campaigns successfully infiltrate systems running outdated operating systems through known exploits. The consequences can include data loss, ransomware attacks, remote surveillance, and privacy violations.

To stay safe, regularly update your Windows system and only install applications from trusted sources.


3. Cracked Software

Cracked software often contains malware or hidden backdoors that can take control of your system. Many users prefer free software, and paid software is frequently cracked by hackers to bypass licensing.

However, downloading cracked versions from the internet is extremely risky. You have no way of knowing who modified the software or whether malicious code has been injected. Many cyberattacks originate from installing cracked software embedded with viruses or backdoors.

Whenever possible, use licensed software and keep it updated to avoid both malware and vulnerabilities in outdated versions.


4. Self-Developed Websites

Most companies today maintain their own websites to establish an online presence. Many also have internal IT teams responsible for building and maintaining these systems.

Just like external software, internal development teams may lack sufficient expertise or experience in cybersecurity. This reality often leads to unnoticed vulnerabilities within company-built systems. These weaknesses may exist in the operating systems, third-party libraries, or even in the system design itself.

To mitigate these risks, companies should continuously invest in security training for their IT teams. In urgent cases, hiring professional penetration testing (pentest) teams to audit and identify vulnerabilities is highly recommended, although it can be costly.


5. Email Phishing Attacks

Phishing emails are one of the most common methods used to compromise business accounts. These attacks require minimal technical skill but are highly effective because they exploit human psychology and general lack of technical awareness.

Common tactics include impersonating banks, government agencies, or reputable companies to trick recipients into entering login credentials or sharing OTP codes. In other cases, phishing emails disguise themselves as legitimate software downloads but actually contain malware.

Many businesses have customer support staff who may lack sufficient cybersecurity awareness, making them easy targets. Simply training employees is often not enough, as phishing techniques are becoming increasingly sophisticated.


6. Weak Operational Processes

Poorly controlled internal processes can allow hackers—or even insiders—to gain access to sensitive information. Some global cybercriminal groups have even deployed insiders by infiltrating companies as employees to create internal backdoors.

Companies with weak hiring, monitoring, and access control processes are especially vulnerable. Large multinational corporations face higher risks due to their scale, but small and medium-sized businesses are not immune—especially from competitors.

To reduce these risks, companies should enforce strict access control policies, granting employees only the permissions they need—and only for a limited time.


Conclusion

Prevention is better than cure. Identifying and addressing security vulnerabilities early is essential to protecting your company’s data, finances, and reputation.

What is Smart Contract ? – explained in plain English

Smart Contract is a contract but instead of written in human language, it is written in a programing language. Like a contract, a Smart Contract defines conditions and financial obligations among participants. Unlike a contract, with a Smart Contract, financial obligations can be executed automatically if conditions are met, without underwriters, lawyers or law enforcement entities.

A contract can protect financial rights of participants only if there is a government enforce and operate. Financial obligations in contracts is money. Money is managed and operated by banks. A Smart Contract is a program and only execute on Blockchain. Blockchain is a network of computers, obey to a protocol that provide services similar to a bank such as : holding balances, transferring value, recording ownership, enforcing rules automatically, and keeping an immutable transaction history.

What Conditions can be added to a Smart Contract ?

Not every statement in contract can be converted to Smart Contract. Smart Contract is a program so it works well with precise numbers and clearly defined if-else conditions such as: money amount, date time, vote counting, temperature.

For example that a company is using Smart Contract to pay employees salary. The Smart Contract can easily implement the agreement that, at every 1st of each month, a fixed amount of money is automatically transferred from the company’s wallet to each employee’s wallets, provided that sufficient funds have been deposited in advance.

Once deployed, the smart contract does not rely on the company’s willingness to pay or on any manual action from accountants or banks. If the date condition is met, the payment is executed exactly as written. If the funds are not available, the payment simply does not occur, making the failure transparent and verifiable to all parties.

In this way, the smart contract replaces trust in the employer or intermediaries with trust in predefined rules and automated execution, ensuring predictable and timely salary payments without human discretion.

However, the smart contract cannot determine whether the employee actually worked, worked well, or should be fired. Those human decisions must be made outside the system. The smart contract only enforces what was clearly defined in advance: who gets paid, how much, and when.

What Conditions can NOT be added to a Smart Contract ?

Smart Contract can not work with Emotions, Quality Judgements, Real Life Events.

For example that a company hires a developer under this agreement:

“The developer will build a high-quality mobile app that meets business needs.
Payment will be made if the work is satisfactory.”

This is where Smart Contract can not replace contract. A smart contract, as a program, can not decide:

  • Whether the app is “high-quality”
  • Whether it “meets business needs”
  • Whether the work is “satisfactory”

These require:

  • Human judgment
  • Discussion
  • Interpretation
  • Sometimes negotiation or compromise

Smart contracts are excellent at enforcing clear rules, but they cannot replace contracts that rely on human judgment, quality assessment, or trust.

How to save $99/year when build app on iOS

If $99 per year is dust to you then this post is not for you 🙂

If it is not, then please take a look !

A fact is that it will cost $99 per year to be able to publish mobile applications to AppStore. For any indie developers that is at the first step of publishing their app, this cost might cause some hesitation.

In case that your application is simple, which is not depends system level APIs such as GPS, File System, Bluetooth, Background Activities or Push Notification, it is possible to make use of PWA feature that is supported by Safari browser which always available on iOS and MacOS.

PWA stands for Progressive Web App. It is a web app, but can be installed into smart phones like a mobile app. Simply put, instead of accessing via a web browser like Safari or Chrome, users can find an icon on their phone, tap it and open the app. This experience makes it feel like it is a mobile app, but under beneath, it opens a browser session and render HTML, JS, CSS code. Although the feel when using PWA app is not as smooth and optimized as when on mobile app, it is acceptable for simple tools, content-first applications, or admin dashboards.

I will take one of my favorite PWA application, Meme Express, as an example. Meme Express is a meme editor that I am using on my Macbook and iPhone whenever I want to make a meme. This meme editor is built with Flutter framework. It has a native app on PlayStore for Android, and a PWA version for the rest of OS including: iOS, MacOS, Window and Linux, essentially, any device can run a browser.

How is PWA version of Meme Express made ?

Framework

Align with mobile first design, Flutter is in used. For simple tools, Flutter is a perfect cross-platform solution, when we can write code once then port to iOS, Android, WebApp, Window and Linux application.

Deploy

For Android version, it is published via Playstore normally, at here: https://play.google.com/store/apps/details?id=com.ease_studio.meme. Unlike other cross-platform framework that utilize in-app web view to mimic mobile app, Flutter ports application to a native Android app.

For iOS version, Flutter can port app to native iOS code as well. But because 99$/year is not an option here, PWA version comes as a rescue.

To publish a PWA version, a hosting server is required. A hosting server requires monthly cost. Luckily, Github Page allow us to deploy a web app from a repository for free and it can be accessed via URL username.github.io/app-name , for example with Meme Express, it is https://ease-studio.github.io/meme-pwa/ . Github Page also allows to map a domain name to it. For example here, https://meme-express.io.vn/ actually points to https://ease-studio.github.io/meme-pwa/ .

Make it Installable

To make a web app installable, aka make it a PWA app, a file manifest.json is added. manifest.json structured is defined at: https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest.

Install PWA app

Below is a demonstration of installing an PWA app to an iPhone, taking Meme Express as an example. Simply put:

  1. Open Safari go to https://meme-express.io.vn/
  2. tap “Share” icon
  3. tap “Add to Home Screen”

How to compete with generative AI as a software engineer ?

Before the decade of AI bursting, software engineering is mostly about writing code that realize requirements. Software Engineers, at some extent, act like a translators between human languages and computer language. This translation today can be accomplished by many generative AI products in seconds and from my observation, generated code has pattern even better than code written by most of developers. It is understandable when companies begin laying off employees that does not match existing AI. It is just a cost optimization – vital part of every business – and also a coldest truth of this life, might be !

What is generative AI good and not good at ?

Recall the flow that each software engineer has to do daily is:

Receive requirements -> Review current state of source code -> Define a target state of source code -> Retrieve information from documents of related tools, libraries and solutions -> Pick solutions -> Actually write code -> Aligning new code to existing code -> Deploy -> Testing -> Measuring results -> Read error messages -> Debugging.

Some steps of this flow is done better by generative AI, and some is better by human:

StepsDescriptionWinner and Why
Receive requirementsto capture goals, constraints, acceptance criteria, performance, security needs, and stakeholders’ expectations.Human
Reason: human are better at eliciting ambiguous needs, negotiating trade-offs, and asking the right follow-ups with stakeholders. AI can help by summarizing long requirement documents and suggesting missing or inconsistent points.
Review current state of source codeto read codebase, architecture, tests, docs, build scripts, dependencies, and CI config.Human + AI
Reason: AI can quickly index, summarize files, find patterns, risky hotspots, and generate dependency graphs. But humans provide domain knowledge, historical context, and recognize subtle intent (business logic, quirks, trade-offs).
Define a target state of source code to design the desired architecture, interfaces, data flows, APIs, and acceptance criteria for the new state.Human + AI
Reason: AI can propose multiple concrete design options, highlight trade-offs. Humans must pick the option that fits non-technical constraints (policy, team skill, product strategy).
Retrieve information from documents of related tools, libraries and solutions to find API docs, migration guides, best practices, configuration notes.AI
Reason: AI can extract key steps, call signatures, breaking changes, and produce concise examples from long docs much faster than manual reading. Humans validate and interpret edge cases.
Pick solutionsto select libraries, patterns, and implementation approaches considering performance, security, license, team skills.Human
Reason: human decision-makers must weigh organizational constraints, long-term maintenance, licensing, and political factors.
Actually write codeimplement features, refactor, add tests, update docs.AI
Reason: AI excels at generating boilerplate, test stubs, consistent code patterns, and translations across languages.
Aligning new code to existing codeensure style, APIs, error-handling, logging, and patterns match the codebase; maintain backward compatibility.Human + AI
Reason: AI can automatically reformat, rename for consistency, and propose refactors to match patterns; humans confirm that changes don’t break conventions tied to tests or runtime behaviors.
Deploypush to staging/production, run migration scripts, coordinate releases, rollback plans.Human
Reason: Humans must coordinate cross-team tasks, business windows, and incident response. AI/automation is excellent at packaging, CI/CD scripts, and repeatable deployment steps.
TestingRun the application locally and manually verify that new changes behave as expected.Human
Reason: Manual testing relies heavily on intuition, product knowledge, and human perception (e.g., UX feel, layout issues, unexpected delays, weird state transitions).
Measuring resultsmonitor metrics, logs, user feedback, testing results, and define success signals.Human + AI
Reason: AI can detect anomalies, summarize metrics, and surface correlations. Humans decide what metrics matter, interpret business impact, and choose next actions.
Read error messagesanalyze stack traces, logs, exceptions, and failure contexts.Human + AI
Reason: AI quickly maps errors to likely root causes and suggests reproducible steps. Humans provide context (recent changes, infra issues) and confirm fixes.
Debuggingreproduce issues, step through code, identify root cause, fix and validate.Human
Reason: AI speeds discovery (identifying suspicious diffs, suggesting breakpoints, generating reproducer scripts), but complex debugging often needs human insight into domain rules, race conditions, and stateful behaviors.

How to compete with generative AI to secure the career as a software engineer ?

Similar to the Industrial Revolution and Digital Revolution, where labors is replaced by machines, some jobs disappeared but new jobs got created. And at some extent, AI, is just another machine, huge one, so, essentially, we are still in the Revolution of Machine era.

The answer for this question is that we need to work on where this huge machine cannot. So far, at the moment of this post, what we can do to compete with AI in software development are:

Transit to Solution Architect

As AI becomes strong at writing code, humans can shift upward into architectural thinking. A Solution Architect focuses on shaping systems, not just lines of code. This involves interpreting ambiguous requirements, negotiating constraints across teams, balancing trade-offs between cost, performance, security, and future growth. AI can propose patterns, but only a human understands organizational politics, legacy constraints, domain history, and long-term impact. By moving into architecture, you operate at a layer where human judgment, experience, and foresight remain irreplaceable.

Become Reviewer / Validator

AI can produce solutions quickly, but it still needs someone to verify correctness, safety, and alignment with real-world constraints. A human reviewer checks assumptions, identifies risks, ensures compliance with business rules, and validates that AI-generated code or plans actually make sense in context. Humans excel at spotting hidden inconsistencies, ethical issues, and practical pitfalls that AI may overlook. Becoming a Validator means owning the final approval — the role of the responsible adult in the loop.

Become Orchestrator

Future engineers will spend less time typing code and more time coordinating AI agents, tools, workflows, and automation. An Orchestrator knows how to decompose problems, feed the right information to the right AI tool, evaluate outputs, and blend them into a coherent product. This role requires systems thinking, communication, and the ability to see the entire workflow end-to-end. AI is powerful but narrow; an Orchestrator provides the glue, strategy, and oversight that turns multiple AI capabilities into a real solution.

Study Broader knowledge

AI is good at depth — consuming a specific library or framework instantly — but humans win by having breadth. Understanding multiple domains (networking, security, product design, compliance, UX, devops, data, hardware) allows you to make decisions AI cannot contextualize. Breadth lets you spot cross-domain interactions, anticipate downstream consequences, and design better holistic systems. The more wide your knowledge, the more you can see risks, opportunities, and real-world constraints that AI cannot infer from text alone.

Expertise in task description

In an AI-driven era, the most valuable skill is the ability to turn a messy idea into a clear, precise, constraints-rich task. This includes defining scope, edge cases, success criteria, and architectural boundaries. AI is only as good as the instructions it receives — so those who excel at describing tasks will control the quality of AI output. Humans who master problem framing, prompt engineering, and requirement decomposition gain leverage: they make AI more accurate, faster, and more predictable than others can.

Business Analyst

The heart of value creation lies in understanding the business, not writing the code. AI cannot replace someone who knows market dynamics, user behavior, budget constraints, prioritization logic, risk tolerance, stakeholder psychology, and regulatory boundaries. A Business Analyst bridges the gap between technology and real-world value. They decide why a feature matters, who it serves, how it impacts revenue or cost, and what risk it introduces — areas where AI can help, but not replace the human nuance needed.

Pentester

Security is one of the hardest domains for AI to master fully because it requires creativity, unpredictability, street knowledge, and adversarial thinking. A pentester does more than run scanners — they exploit human behavior, spot surprising vulnerabilities, and think like an attacker. Humans who understand security fundamentals, threat modeling, social engineering, and advanced exploitation techniques will stay in demand. AI helps automate scanning and code analysis, but a creative pentester stays ahead by understanding motives, tactics, and real-world constraints.


Essentially, it is to use AI as a super-assistant
that can write code very well
to realize our intentions.

What is Refactor and why it is matter ?

For someone with no programming experience, the word “refactor” can be confusing at first, because it’s mostly used in coding. For a simple explaining, refactor is Making something better or clearer without changing what it does.

Why Refactoring when there is nothing change ?

If it works, don’t touch it” is a principle that is still valid in real world. It’s truth, pragmatic and is recommended at some extent when we do not have enough understanding about system we are working on. From business perspective, Refactoring feels unproductive when there is no new features added to system, but, just like a business, sometime we need to restructure processes, reorganize people and rearrange tasks to maximize outcomes, programing process also need refactoring to optimize coding experience which help source code more readable, maintainable, and scalable. These benefits, in turns, accelerate developers when adding new features or fixing bugs later on.

What is Readable code ?

Readable code is code written clearly so another developer, or future you, can read it quickly and know what’s going on, sometime just by guessing via variable names and function names. Some tactics can be applied to ensure readable code are:

  • Clear naming: Variables, functions, and classes have names that explain their purpose.
  • Short, focused functions: Each function does one thing, not many things.
  • Consistent formatting: Proper indentation, spacing, and line breaks.
  • Avoids unnecessary complexity: No overly clever tricks, Straightforward logic.
  • Helpful comments: Explain why, not what.
  • Use of standard patterns: Code follows common conventions so others instantly recognize the structure.

What is Maintainable code ?

  • Readable: as explained as above
  • Well-organized: Code is structured logically into modules, functions, or classes
  • Consistent: Follows the same style, naming, and patterns everywhere.
  • Well-tested: Covered by tests to catch bugs early and safely.
  • Documented: Has comments or docs explaining why and how things work.
  • Flexible: Easy to modify, extend, or adapt without breaking existing code.

What is Scalable code ?

  • Efficient: Uses memory and CPU wisely, Avoids unnecessary heavy operations.
  • Modular: Pieces of code can be separated or duplicated easily
  • Asynchronous / non-blocking when needed: Doesn’t freeze the whole system while waiting for one slow task.
  • Uses good architecture: Clear layers, Can split into microservices or separate components if needed.
  • Uses proper data structures: For example, using a Map instead of a List for fast lookups.
  • Database scalability: Indexes, caching, batching queries, sharding, etc.

Refactor safety

Because the goal is to keep system working as the same while rewriting codes, there must be a metric indicate sameness, or early detect differences in system behaviors. This is where Test Driven Development shines.

Writing Test is mistakenly overlooked by inexperience developers. Beginners usually think programing job is just to write code, see it run then move on writing another code. Writing tests looks like an extra work or an annoying requirement. This is okay just as a young men does not understand “karma”. And karma for this overlooking usually are:

  • Bugs keep coming back
  • Bugs evolve when there is more code added
  • Take so much time for debugging
  • Source code become a mess and a small change can take months to add

When bugs bring enough pain, developers begin more experience.

Test Driven Development (aka TDD)

Test-Driven Development (TDD) is a software development process where you write tests before writing the actual code.

TDD follows a repeating 3-step loop:

  1. Write a failing test ( yes, always fail first ! )
    • The test describes what the code should do.
    • It fails because the feature doesn’t exist yet, or the bug is not fixed yet.
  2. Write the minimum code needed to make the test pass
    • Not perfect code, just enough to pass the test.
  3. Refactor – Clean up the code
    • Improve readability, maintainability, scalability
    • Keep the tests passing.

Then repeat the cycle for the next feature and bug fixing.

Tests ideally can simulate the UX that users will engage on real product. This can not be 100% achieved but keep this principle in mind will help a lot to write good tests. Depends on how closely a test to real world UX, tests can be classified to 3 levels: Unit Test, Integration Test, and E2E Test.

Unit Test

Unit Test is ideal to test behaviors of a function or a class. In each unit test, we can test output of a function given a particular input. We can anticipate what inputs can be, even unrealistic ones (hackers usually input unrealistic ones) , to ensure our functions keep functioning regardless what input is. Unit tests can be used as a debugging tool when we can test directly a part of system without try reproducing via UI/UX. For functions that is well guarded by unit tests, developers can feel more confident to add changes or refactor it because bugs can be caught early.

Integration Test

Integration tests are tests that check how multiple parts of system work together. Functions, Classes and Flows can be tested on how they are interacting together inside a system. It ensures that every “pieces” of the system are integrating properly. Similar to Unit Test, we can anticipate and simulates Flows to can catch bugs soon.

E2E Test

E2E (End-to-End) tests are the tests that simulate a real user using the real app, by actually click buttons and typing text.

This is ultimate form of Test that can catch bugs that unit or integration tests cannot. E2E Tests test the app in an environment closest to production. They validate the entire system from UI/UX to data storage. But it is the hardest tests to make when a real system need to be deployed for E2E tests can execute. Simulating user behaviors by coding requires more effort. This is why many teams usually stop at Integrating Tests and it is totally ok when majority of bugs can be catch at level of Integration Test. Writing E2E Tests is time consuming so we should only write it for bugs that un-produceable at Integration Test level. These bugs are high-level bugs and it should be addressed by high-level tests, and they mostly about concurrency, timing and resources:

  • Race Condition: A situation where the correct behavior of a program depends on the relative timing or interleaving of multiple threads or processes. It’s about uncontrolled timing causing wrong results.
  • DeadLock: Two or more threads/processes are waiting on each other indefinitely, preventing progress. As the result, system freezes because resources are locked in a circular wait.
  • Livelock: Threads or processes keep changing state in response to each other but make no actual progress. As the result, CPU or threads are active, but nothing gets done.
  • Starvation: A thread never gets access to a needed resource or CPU because other threads dominate it. As the result, resource exists, but some threads never get a chance to execute.
  • Atomicity violation: A set of operations that should be executed as a single, indivisible unit is interrupted, causing incorrect results.
  • Order violation: Correct behavior depends on operations happening in a specific order, but the order is not guaranteed that eventually leads to incorrect results.
  • Heisenbug: A bug that disappears or changes when you try to observe it (e.g., by debugging, logging, or adding print statements). This sounds like quantum computing but yes, it does exists. These bugs often caused by concurrency, timing, or memory issues.
  • Data corruption: Shared data is modified concurrently without proper synchronization, resulting in invalid or inconsistent values.
  • Lost update: Two concurrent operations overwrite each other’s results, causing data loss.
  • Dirty read / inconsistent read: A thread reads a partially updated or uncommitted value from another thread or transaction and then produce wrong results.
  • Priority inversion: A low-priority thread holds a resource needed by a high-priority thread, causing the high-priority thread to wait unnecessarily.

In conclusion, to Refactor code safely, we need a lot of tests, good tests one !

A thought about language

It is certainly that there is a lot of programming languages on the market. Each language creates itself job positions and even programming “religion” where engineers prefer using a certain language over others, and thanks to that, the software development market can thrive because the diversity in language increase the scarcity in workforce.

So why some language offer higher salary than others ?

Well, language is tool, each tool is more appropriate for a certain purpose. Salary is the compensation from the budget assigned for a purpose. So actually there is no standard market price assigned to each language. It still is the supply-demand game. The difference is the demand is influenced by big boys in the industry. Big boys create programing languages, frameworks that overcome limitations of the ones exists before. The limitation can be speed, memory efficiency, friendly syntax, built-in solution for repeatable tasks. As the result, it can save money in renting physical resource (computers) and save working hours (constructing and error fixing) and that savings also contribute to the compensation, or the salary.

Can an engineer learn multiple language ?

Absolutely Yes.

Learning a language is always hard and time-consuming. There is a lot to remember: syntax. And syntax can be translated from one to another by the same principle as human language. So far, for each language, what we need to remember are:

  • How to declare variable
  • How to write conditional check (if-else)
  • How to do the loop (for-while)
  • How to separate code in reusable blocks (class, method, function, interface)
  • How to handle concurrency (process, thread, event loop)
  • What libraries are offered out-of-the-box per each language.

The tactic is, for the first language, learn it carefully and practice a lot. For new languages, compare it to the one we knew, and find the translation between syntax sets, then practice a lot.

Another tip is to search for open-source projects, and read their code. This is also a quickest way to learn from top engineers.

Is it worthy to know more than one language?

Yes, I think.

If we only need a stable job, one language is enough. But remember that technology changes everyday, and any project has the starting date and the end date. So, ensure your adaptability.

If we are interested in technology, learning new languages can provide us a deeper understanding about computer as well as to see more than 1 way to solve same issues. It keeps us open-minded, curios and provide a broad range of knowledge, which is a truly stability, so far as what I learn from many professionals.

And, the whole programing activities is a career, not a single language itself.

Is it tired to know more than one language?

Yes, obviously. No need to explain.

A must read before start learning AI

Natural Language Processing (NLP) is a major research field of AI and to almost developers, it sounds like a miracle. Lately I have an interest in this field since the noticeable viral news of GPT-3 model. I decided to learn to make use of it as a tool before somehow it will replace developer job in the future as many predictions from many illustrious figures. But the more I study about it, the more nothing I know. There are too many background knowledge to know before understanding each word on the GPT-3 paper. Below is a quick summary about works behind the scene that hopefully useful to developers like me who wants make a leap to catch up with the AI progress.

List of keywords

It is inevitable long and exhausting journey to make sure we can understand fairly basic about below terms:

  • Convolutional Neuron Network, Recurrent Neuron Network, Activation Function, Loss Function, Back Propagation, Feed Forward.
  • Word Embedding, Contextual Word Embedding, Positional Encoding.
  • Long – Short Term Memory (LSTM).
  • Attention Mechanism.
  • Encoder – Decoder Architecture.
  • Language Model.
  • Transformer Architecture.
  • Pre-trained Model, Masked Language Modeling, Next Sentence Prediction.
  • Zero-shot learning. One-shot learning, Few-shot learning.
  • Knowledge Graph.
  • BERT, GPT, BART, T5

What exists before BERT and GPT ?

There was a lot of researches and works existed in NLP field. Work on NLP field means to solve below common Tasks:

  • Tagging Part of Speech.
  • Recognising Named Entities.
  • Sentiment Classification.
  • Question & Answering.
  • Text Generation.
  • Machine Translation.
  • Summarization.
  • Similarity Matching.

SpaCy and NLTK is two most famous libraries in NLP field that provide tools, frameworks and models solving a few Tasks above, but not everything. Each Task usually had its own model and there is no reusing or transferring between models, until the Transformer Architecture is published. With its amazing performance and ability of Transformer Architecture, researchers begin to think about using this architecture to perform above NLP tasks, to have one single model can do it all. And the result is the BERT and GPT models which both are using Transformer. A fact is that, BERT is powering the Google search engine, and GPT-3 is the one powering ChatGPT application. There are also more applications making used of these models can be found around Internet.

Some Core Challenges when doing NLP

No matter what method is applied, the challenges that forming the NLP field is still the same:

  • Computer does not understand words, it understands numbers. Find a method to convert each word in a sentence into a vector (a group of numbers) that: given 2 words with similar meanings, 2 vectors can have a close-distance to present the similarity.
  • Given a sentence with many words and variable length, find a vector can present the sentence.
  • Given a passage with many sentences and variable length, find a vector can present the whole passage.
  • From a vector of a word, sentence or passage, find a method to convert it back to words/sentences/passage. This task in turn become the Machine Translation, or Text Summarization.
  • From a vector of a word, sentence or passage, find a method to classify it into some senses/intents. This task in turn become Sentiment Classification.
  • From a vector of a word, sentence or passage, find a method to calculate the similarity to other vector. This task in turn become Question & Answering, or Text Generation, Text Suggestion.

It will be too long to dive into each keyword here so please Subscribe button to receive upcoming posts from my learning journey.

Thanks for reading!

Microservices Tradeoffs and Design Patterns

Let aside the reason why we should and should not jump into Microservices from previous post , here we talk more about what Tradeoffs of Microservices and Design Patterns that are born to deal with them.

Building Microservices is not easy like installing some packages into your current system. Actually you will install a lot of things :). The beauty of Microservices lies on the separation of services that enable each module to be developed independently and keep each module simple. But that separation also is the cause of new problems.

More I/O operations ?

First issue that we can easily to recognize is the emerging of I/O calls between separated services. It exactly looks like when we integrate our system to 3rd party services, but this time, all that 3rd party services is just out internal ones. To have correct API calls, there will be efforts to document and synchronize knowledge between teams handling different services.

But here is the bigger problem, if every services has to keep a list of another services addresses (to call their APIs), they become tight coupled, means strong dependent between each other and it destroys the promised scalability of Microservices. So it is when the Event-Driven style comes to rescue.

Event Driven Design Pattern

Example tools : RabbitMQ, ActiveMQ, Apache Kafka, Apache Pulsar, and more

Main idea with this pattern is to allow services not need to know about each others addresses. Each service just need to know an event pipe, or a message broker and entrust it for distributing its message and feeding back data from other services. There will be no direct API call between services. Each services only fires some events to the pipe, and listen on some events happened from the pipe.

Along with this design pattern, the mindset on how to storing data is required some escalations too. We will not only store STATE of entities, but also store the stream of EVENTs that construct that STATE. This storing strategy also is very effective when dealing with concurrent modifications on the same entity that can cause inconsistent in data. There are 2 approaches to store and consume events : by using the Queue and using the Log that we will discover in later topics.

More Complex Query Mechanism ?

It is obviously there will be moments that we need to query some data that need the co-operation between multiple services. In the past with monoliths style, when all data of all services is located in the same database, writing an SQL query is simple. But in Microservices style, it can’t. Each service secures its own database as a recommended practice. We suddenly can’t JOIN tables, we lost the out-of-the-box rollback mechanism from database’s Transaction feature in case of something wrong with storing data, we may have a longer delay while each service may have to wait for data from other services. And those obstacles turn Event Driven to be a “must have” design for Microservices system since that design is the foundation to support patterns solving this Querying issue, most common are Event Sourcing, CRSQ, and Saga.

Event Sourcing

It can be a bit confusing between terms Event Driven vs Event Sourcing. Event Driven is about communication mechanism between services , since Event Sourcing is about coding solution inside each service to retrieve a state of an entity: instead of fetching the entity from the database, we reconstruct it from an event stream. The event stream can be stored in many ways: it can be stored on a database’s table, or it can be read from Event-Driven supported components such as Apache Kafka, or RabbitMQ, or using some dedicated event stream database like EventStore, etc. This method brings new responsibility to developers that they will have to create and maintain the reconstructing algorithms for each type of entity .

As mentioned at previous section, this strategy is helpful when dealing with concurrent data modification scenario, something like collaboration features that can be seen in Google Docs or Google Sheets, or simply to deal with scenario that 2 user hit “Save” on the same form at very closed moments. But this reconstructing way is not so friendly to a more complex query which is so natural with traditional database like Oracle or PostgresSQL, the SELECT * WHERE ones. So, to cover this drawbacks, each service usually also maintain a traditional database to store states of entities and using it for querying. And this combination form a new pattern called : CQRS (Command and Query Responsibility Segregation) where the read and the write on an entity happens on different databases.

CQRS (Command and Query Responsibility Segregation)

As mention above, this pattern is to separates read and update operations for a data store. A service can use Event Sourcing technique for update an entity, or construct an memory based database such as H2 database to quickly store updates on entities, while as quick as possible to persist the calculated states of entities back to a SQL database for example. This pattern prevents the data conflict while there are many updates on a single entity come at the same time while also keep a flexible interface for query data.

This pattern is effective for scaling purpose since we can scale the read database and the write database independently, and fit for high load scenario when the writing requests can complete quicker because it reduces calls to database with potential delay from locking mechanism inside databases. Quicker response mean there will be more room for other requests, especially in thread-based server technology such as Servlet or Spring.

A drawback of this pattern is the coding complexity. There is more components join in the process, there will be more problem to handle. So it is not recommended to use this way in cases that the domain or business logics are simple. Simple features is nice fit with traditional CRUD method Overusing anythings is not good. I also want to remind that if the whole system does not have special needs on the load, or write-heavy features, it is not recommended to switch to Microservices too. (reason is here )

Saga

Saga means a long heroic story. And the story about Transaction inside Microservices is truly heroic and long. Transaction is an important feature for a database that aim to maintain the data consistency, it prevents partial failure when updating entities. With distributed services, we are having distributed Transactions. Now, the mission is how to co-ordinate those separated Transactions to regain attributes of a single Transaction : ACID (atomicity, consistency, isolation, durability) over distributed services . We can understand simply that : Saga is a design pattern aim to form the Transaction for Microservices.

Saga patterns is about what system must do if there is a failure inside a service. It should somehow reverse some previous successful operations to maintain data consistency. And the simplest way is to send out messages to ask some services to rollback some updates. To make a Saga, developers may have to anticipate a lot scenarios that an operation can fail. The more high level solution for rollback mechanism is to implement some techniques like Semantic lock or Versioning entity. We can discuss about this in other topics. But the point here is it also brings much complexities to the source code. The recommendation is to divide services well to avoid writing too much Saga. If there are some services that are tight coupled, we should think about merging them into one Monoliths service again. Saga is less suitable for tight coupled transaction.

More Deployment Effort ?

Back to Monoliths realm, the deployment means running a few command lines to build an API instances and to build a client side application. When go with Microservices, obviously we are having more than 1 instance, and we need to deploy each instance, one by one.

To reduce this effort, we can use some CI/CD tools such as Jenkins, or some available Cloud base CI/CD out there. We also can write ourself tools , it won’t be difficult. But there is still some more issues than just running command lines.

Log Aggregation

Logging is vital practice when building any kind of application to provide the picture of how system is doing and to troubleshoot issues. Checking logs on separated services can be not very convenient in Microservices so it is recommended to stream logs to one center. There are many tools dedicated for this purpose nowadays such as GreyLog or Logstash. The most famous stack for collecting, parsing and visualizing for now is ELK which is the combination of ElasticSearch + Logstash + Kibana. The drawback of those available logging technology is it requires a bit much RAM and CPU, mostly to support searching logs. For small projects, preparing a machine that is strong enough to run ELK stack may not very affordable. Logstash requires about 1-2 GB is plenty enough. GreyLog requires ElasticSearch so it also require about 8GB RAM and 4 Cores CPU. ELK is much more than that.

Health Check & Auto restart

Beside Logging, we also must have a way to keep track availability of services. Each service may have its own API /healthcheck that we can have a tool to periodically call to to check whether it’s alive or not. Or we can use proactive monitoring tools such as Monit or Supervisord to monitor ports / processes and configure its behavior when some errors occur, such as sending emails or notifications to the Slack channel.

Beside Heath Check, each service should have auto-restarting ability when something take it down. We can configure for a process to start up whenever the machine is up by adding scripts to /etc/init.d or /etc/systemd for most of Linux server. For processes, we can make use of Docker to automatically bring services up right after it is down. For the machine itself, if we use physical machine, we should enter BIOS and set up Auto-Restart when power is on. If we use Cloud machines, it is no worry.

Those techniques are not only recommended for Microservices but also for any Monoliths system to ensure the availability.

Circuit Breaker

This is for when bad things happen and we have no way to deal with it but accepting. There is always such situation is life. For some reasons, one or many services is down or become so slow due to network issues that it will makes user wait long just for a button click. Most of users are impatient and they will likely to retry the pending action, a lot and you know system can got worser. It is when a Circuit Breaker take action. It’s role is just similar to electric circuit breaker , is to prevent catastrophic cascading failure across system. The circuit breaker pattern allows you to build a fault tolerant and resilient system that can survive gracefully when key services are either unavailable or have high latency.

The Circuit Breaker must be placed between client and actual servers containing services. Circuit Breaker has 2 main states: Closed, Open. The rules among those states are:

  • At Closed state, Circuit Breaker just forward request from clients to behind services.
  • Once Circuit Breaker discovers a fail request or high latency, it change status to Open.
  • In Open state, Circuit Breaker will return errors to client’s requests immediately, so the user acknowledge the failure and it is better than let users wait, and it also reduces the load to the system.
  • Periodically, Circuit Breaker makes retry-call to behind services to check their availability. If behind services is good again, it changes to Closed state, if not it remain Open state.

Luckily we may don’t have to implement this pattern ourself. There are available tools out there such as : Hystrix – a part of Netflix OSS, or Istio – the community one

Service Discovery

As we mentioned at Event Driven section, services inside a Microservices no need to know each own addresses by using an Event channel. But what if the team does not familiar with Event style and decide not to use it, or the services is simple enough to just expose REST APIs only. Using Event Driven is not a must-do, and in this case, how do we solve the addressing problem between services.

When system need to be scaled, there will be more instances for one or many services need to be added, or removed, or just be moved around. To let every services know the address (IP , port ) of others, we need a man in the middle that keep the records about service’s addresses and keep it up to date. This module is called Service Discovery ad usually be used along with Load Balancing modules. We may discuss about this more on other topics.

We also no need to create this component from scratch. There are some tools out there such as : etcd, consul, Apache ZooKeeper. Let’s give a try with them.

Ending

Above is an overview of what we need to know when moving to Microservices. Make sure you google them all before really starting. Each of patterns will have its pros and cons and overcoming solutions that another topics will cover. Thanks for reading !!