What is Load Balancing?

Load balancing is all about making sure no single server gets overwhelmed. Picture this: your favorite website or app can get crazy busy at times. Without load balancing, one server might end up feeling like it’s carrying the weight of the world, leading to slow response times or even crashing.

So, what does load balancing do? It’s like a traffic cop for network requests, spreading them out among multiple servers. This way, no server gets too bogged down, and everything runs smoothly.

Load Balancing Algorithms

  1. Round Robin: Servers take turns handling requests.
  2. Least Connections: The server with the least load (fewest active connections) gets first dibs on new requests.
  3. Weighted Round Robin: This one’s like Round Robin, but servers can have different “weights” based on their capacity – heavier servers get more requests.
  4. Least Response Time: Sends traffic to the server that’s quickest to respond – it’s all about efficiency.
  5. Hash: Distributes requests based on a key you define, whether it’s the client’s IP address or the request URL. If the set of servers changes, NGINX Plus can even apply a consistent hash to minimize the reshuffling of workloads.
  6. IP Hash: The IP address of the client decides which server gets the special treatment. So, when a request comes in, the server is chosen based on the client’s IP address.
  7. Random with Two Choices: This one randomly picks two servers and then makes a smart move. It applies the Least Connections algorithm to decide which server gets the request.

Benefits of Load Balancing

  • Scalable
  • Reduces downtime
  • Flexible
  • Efficient

Whether it’s at the application layer, transport layer, or network layer, load balancing ensures everything is running smoothly.

GitHub Tips and Tricks

GitHub is a developer platform that allows developers to create, store, and manage their code. If you’re new to GitHub, or if you’ve been using it for years and have yet to look into shortcuts, I figured I’d share a few handy GitHub tips and tricks.

GitHub Keyboard Shortcuts

If you navigate to a repo page, and press ? (or Shift + /) GitHub will show you a modal with a list of quick keyboard shortcuts, as well as a link that displays all the available shortcuts.

GitHub shortcuts

One of my favorite ones to use is typing / or s when you’ve navigated to a repo page, since it allows you to pull up the file search.

Autodelete GitHub Branches

You can automatically delete GitHub branches after pull requests have been merged into your repo. This is great for managing your repo’s branches so that they don’t get out of control. To set up the automatic deletion of branches, navigate to the settings for a specific repo. On the “General” settings page, under the “Pull Requests” section, select “Automatically delete head branches.”

Link to Specific Lines of Code in a GitHub Repo

If you click the number beside a line of code, it will highlight the line and display a few menu options. If you click “Copy permalink” you’ll have access to a link that will link to the code snippet even if the file is later updated or deleted on the main branch. If you hold down shift while selecting lines of code, you can select several lines to highlight and link to.

Close GitHub Issues Automatically with Keywords in your Commit Messages

You can automatically close issues fixed by commits by using a keyword followed by the issue number in the commit message, i.e. git commit -m "fixes #30"

Here’s a list of all the keywords you can use to automatically close issues:

close #30
closed #30
closes #30
fix #30
fixed #30
fixes #30
resolve #30
resolved #30
resolves #30

Handy GitHub URLs

GitHub uses a few URL patterns that are handy for getting access to diffs of code or even user avatars:

  • Avatars: https://github.com/<username>.png
  • Diff of a commit: https://github.com/<repo-owner>/<repo>/commit/<sha>.diff
  • Patch of a commit: https://github.com/<repo-owner>/<repo>/commit/<sha>.patch
  • Diff of a pull request: https://github.com/<repo-owner>/<repo>/pull/<id>.diff
  • Patch of a pull request: https://github.com/<repo-owner>/<repo>/pull/<id>.patch
  • Latest release: https://github.com/<repo-owner>/<repo>/releases/latest

Format your GitHub README.md with Markdown

When visiting a GitHub repo, GitHub will serve the repo’s README.md. You can make these documents pretty elaborate by including a project overview, info on how to run the project locally, deployment info, etc. I like to use a project’s repo as the single source of truth for that project and keep it updated as processes change and as adjustments are made to various environments. You can find some basic markdown formatting info via GitHub’s documentation. One helpful tip for markdown formatting that I enjoy using, is that the <details></details> tags allow you to hide/show content via a simple accordion.

Host Web Pages and Simple Applications with GitHub Pages

You can host a GitHub Pages site for free via your GitHub account. This is great for simple websites and applications. You can even customize the domain URL, but the out-of-the-box URL is <your-github-username>.github.io/<repo-name>. You can find out more about using GitHub pages here.

What is the Difference Between null, NaN, and undefined in JavaScript?

The other day I was thinking about how earlier last year, I was interviewing like crazy, and sometimes I had recruiter phone screens where I was quizzed on various JavaScript terms. As I think of some of the questions I’ve been asked previously, I plan to write articles focusing on these questions and answers.

NaN

NaN means Not a number, and it denotes the value of an object is not a number. If you look at typeof NaN it will return 'number' since NaN is a numeric data type that is undefined as a real number. NaN can be returned if you do one of the following:

  1. Convert undefined into a number
  2. Convert a non-numeric string into a number
  3. Divide zero by zero
  4. Divide infinity by infinity
  5. Operation where the result is not a real number
  6. Method/expression’s operand is or gets coerced to NaN

null

null means the object is empty. It’s an assignment value that can be assigned to a variable that has no value.

undefined

undefined means that the object doesn’t have any value and is undefined. This happens when you declare a variable and don’t assign a value to it.

How to update Node to the latest version?

Node.js is a JavaScript runtime environment that runs on the V8 JavaScript engine and executes JS code outside a web browser. When developing locally, you’ll want to ensure that you keep Node updated for various projects to ensure you’re protecting applications from vulnerabilities and bugs.

NVM is a great tool for installing different versions of Node and switching between different versions for various projects. You’ll first want to install NVM. Once installed, you can install versions by doing the following:

Run nvm install [version] within the command line (replacing [version] with the version of Node you’d like to install).

Useful NVM commands

// check version of Node
node -v // can also use node --version

// list all locally installed versions of Node
nvm ls

// install specific version of Node
nvm install 20.10.0

// set default version of Node
nvm alias default 20.10.0

// switch version of Node
nvm use 20.00.0

// install latest stable version of Node
nvm install stable

How to specify what version of Node to use in a specific project

Within a project’s root directory, you can specify the version of Node that NVM should load by creating a .nvmrc file. You can generate this file by running the following command in the project’s root directory: node --version > .nvmrc

How to update dependencies in your package.json?

To update dependencies in package.json files, you can use npm, the package manager for Node.js:

  1. In the terminal, navigate to the root directory of your project and run npm install or npm i to install all the dependencies in your package.json
  2. To update a specific dependency, run npm update package-name (package-name is the name of the dependency you want to update, so adjust that text within this command).
  3. To update all dependencies, run npm update

To update npm itself, run the following:

npm install -g npm@latest

Useful Regular Expressions for Developers

A regular expression, or regex, is a sequence of characters that specifies a match pattern in text. Often times regex is used for form validations and string-searching algorithms. Here are a few regex that are handy for developers:

Letters

  • Domain: ^([a-z][a-z0-9-]+(\.|-*\.))+[a-z]{2,6}$
  • Email: ^[_]*([a-z0-9]+(\.|_*)?)+@([a-z][a-z0-9-]+(\.|-*\.))+[a-z]{2,6}$
  • Letters only: ^[a-zA-Z]+$

Numbers

  • Numbers only: ^[0-9]*$
  • Positive numbers: ^\d*\.?\d+$
  • Negative numbers: ^-\d*\.?\d+$
  • Numbers with spaces and parenthesis: /^(?:\+\d{1,3}|0\d{1,3}|00\d{1,2})?(?:\s?\(\d+\))?(?:[-\/\s.]|\d)+$/
  • Phone number: ^\+?[\d\s]{3,}$
  • Phone number with code: ^\+?[\d\s]+\(?[\d\s]{10,}$

Useful for Inputs

  • Letter and numbers only: ^[A-Z0-9]+$
  • Match blank input: ^\s\t*$
  • Match no input: ^$
  • Match new line: [\r\n]|$
  • Match URL: ^http\:\/\/[a-zA-Z0-9.-]+\.[a-zA-Z]{2,3}$
  • Match white space: ^\s+$
  • Match multiple white space: ^.\s{2,}.$

Handy Git Commands

Git is a version control system that tracks changes in a set of files, which is used by developers to coordinate work done for various projects. Here are some useful git commands that can help with your workflow:

General Commands

  • git status to see what changes have been made locally
  • git add . to commit all locally edited files in the repo
  • git add <file> to add a file to the next commit
  • git rm <file> to delete a file in the next commit
  • git mv <file> to rename a file in the next commit
  • git add -p is useful if you’ve done too much work for one commit, ? is a useful command to print all
  • git cat-file -p <sha> prints the contents of blobs (sha refers to the SHA or hash that git assigns to each commit)
  • cat .git/HEAD to see what HEAD is pointing to

Stashing

Stashing your work is useful if you’re moving between branches when you’re in the middle of work. It’s a safe, non-destructive way to save your work.

  • git stash to save uncommitted work
  • git stash list to view the current stashes that are available
  • git stash apply applies the last stash
  • git stash apply stash@{0} to apply a specific stash (in place of the 0 you can add the number associated with the stash from your git stash list that you’d like to apply)
  • git stash --include-untracked to keep untracked files in your stash
  • git stash save "WIP: working on recent bug fix" in place of the text in the quotes here, you can add a name for easy references when viewing the list of your stashes and figuring out which stash to apply on your current branch
  • git checkout <stash name> -- <filename> grabs a single file form a stash
  • git stash show stash@{2} to show the files changed

Keeping Your Stash Clean

  • git stash drop to remove the last stash
  • git stash clear to remove all stashes

Logging

  • git log to view an overview of the most recent git commits
  • git log --since="yesterday" to view commits from a specific time period. You can also pass arguments like git log --since="2 weeks ago"
  • git log --name-status --follow -- <file> to log files that have been moved or renamed
  • git log --diff-filter=R --find-renames to find files that have been renamed
  • git show <commit> to show commit and its contents
  • git show <commit> --stat show files changed in commit
  • git show <commit>:<file> look at a file from another commit

Fixing Mistakes

  • git checkout -- <file-path> overwrites the working area file with the staging area version from the last commit (this operation overwrites without warning so use with caution)
  • git clean will clear your working area by deleting untracked files (this operation cannot be undone). Use the --dry-run flag to see what will get removed
  • git reset moves the HEAD pointer, modifies files for commits (can change history)
  • git revert <commit> is the safe reset (creates a new commit that introduces the opposite changes from the specified commit, the original commit stays in the repo)
  • git reset --hard HEAD use this command if your staging area has gotten really messed up and you want to blow away all of your local work
  • git commit --amend if you need to amend your latest commit
  • RERERE (Reuse Recorded Resolution) is a tool that remembers a previously used solution for a merge conflict. Set git config rerere.enabled true within a project to have access to this tool. You can also set it globally with git config --global rerere.enabled true

Rebasing

Rebasing your feature branch with main will help keep your development work up-to-date with the latest changes that have been committed to the repo. This will help make merge conflicts more manageable whenever it’s time to merge in your feature work.

  • git rebase main makes history of current branch cleaner and makes managing merge conflicts easier
  • git rebase -i <commit to fix> addressing specific commits

Working with GitHub

  • git clone <project reference to clone a GitHub repo locally
  • git pull performs a git fetch && git merge to ensure the latest version of a branch has been updated on your machine
  • git push origin <name-of-branch> to push any changes to the remote repo
  • git pull --rebase will fetch, update your local branch to a copy of the upstream branch, then replay any commits you made via rebase (this doesn’t work well on branches with local merge commits, it works best when branching off master and working on a feature)

Local Destructive Operations

When performing a destructive operation, make sure you properly stash your work so you don’t accidentally delete any of your work in progress. Use git stash --include-untracked to include working area changes in your stash.

  • git checkout --<file> if file is presnt in staging, it will be overwritten
  • git reset --hard overwrite changes that are staged and in working area
  • rebase, amend, and reset can rewrite history (if your code is hosted or shared, never run git push -f which forces a push of your changes)

Configuring Your Editor

To customize which editor git opens when you run a commit with no -m flag, a merge, or rebase, run the following command:

git config --global core.editor <your_editor>

In the place of <your_editor>, add the command associated with your editor of choice:

  • atom: atom --wait
  • emacs: emacs
  • sublime: subl -n -w
  • vi: vi or vim
  • vscode: code --wait

How to Manage State by Using the React Context API

When I work on large-scale applications, I use Redux for state management. However, when it comes to building smaller applications and smaller personal projects, Redux can feel cumbersome. So, what’s the best light-weight solution for state management of these smaller applications? React hooks work really well for smaller applications, but sometimes you need to share state between components, and passing that state through components via props can get a little clunky. That’s where React Context comes to the rescue.

By utilizing the React Context API, you can avoid prop drilling. It also helps keep your components cleaner and simpler.

Let’s walk through what this would look like if we’re adding React Context to an application. First, I like to organize my context within a contexts folder within the src directory. Then I create a context file where all the global state will live. For this example, let’s call the file ItemContext.js:

import { createContext, useState } from "react";
import PropTypes from "prop-types";
const ItemContext = createContext();
const ItemProvider = ({ children }) => {
  const [items, setItems] = useState([]);
  const addItem = (item) => {
    const index = items[items.length - 1].id + 1;
    item.id = index;
    const updatedItems = [...items, item];
    setItems(updatedItems);
  };
  const editItem = (id, item) => {
    const index = items.findIndex((e) => e.id === id);
    const updatedItems = [...items];
    updatedItems[index] = item;
    setItems(updatedItems);
  };
  const removeItem = (id) => {
    const updatedItems = [...items];
    setItems(updatedItems.filter((item) => item.id !== id));
  };
  const context = {
    addItem,
    editItem,
    items,
    removeItem,
  };
  return <ItemContext.Provider value={context}>{children}</ItemContext.Provider>;
};
export { ItemContext, ItemProvider };
ItemProvider.propTypes = {
  children: PropTypes.object,
};

Next, within the src directory, if you don’t already have a hooks directory, create one where we’ll add a new hook file, useItemContext.js:

import { useContext } from "react";
import { ItemContext } from "../contexts/ItemContext";
const useItemContext = () => {
  return useContext(ItemContext);
};
export default useItemContext;

This file probably looks fairly small, but it will help us cut back on copying and pasting the same lines of code when we want to reference this global state. Now, when we want to access the global state or update the state via various components, we can do so by importing the context hook:

import useItemContext from "../hooks/useItemContext";
const ExampleComponent = () => {
  const { addItem, editItem, removeItem } = useItemContext();
  const handleAdd = (item) => {
    addItem(item);
  };
  const handleRemove = () => {
    removeItem(item.id);
  };
  const handleSave = (item) => {
    editItem(item.id, item);
  };
  return (
    {Add your presentation logic here}
  );
};
export default ExampleComponent;

Lessons Learned from a Mass Tech Layoff

This year was the first time I was ever laid off from a company, and I figured I’d share my lessons learned from the experience. Maybe you’ll find them helpful if you ever find yourself in a similar situation or if you’re going through the same thing at the moment.

Lessons I learned from getting laid off from my Senior Software Engineering role:

  1. Instead of diving into job hunting immediately, take some time to rest beforehand. I dove into job hunting immediately, although I was still feeling devastated from being laid off from a company that had been a dream job for me. I was processing my grief over losing a job while also feeling extremely exhausted from staying up late studying for technicals and waking up early for my scheduled interviews. This made it difficult to perform at my best during those interviews.

  2. Don’t apply to too many places at once. Right after getting laid off, I panic-applied to a lot of companies. As a result, I had several companies responding to me at the same time to set up interviews. My calendar was crammed with interviews – recruiter calls, technicals, and take home assessments. I ended up feeling extremely overwhelmed and was spread too thin, and ultimately bombed too many interviews because I overextended myself. If I could go back and do things differently, I would have been more selective at the beginning of my job hunt. That way I wouldn’t have been so exhausted in the beginning.

  3. Filter the unsolicited advice you’re getting from others and focus on what makes sense for you and your situation. I had a lot of friends/family give me their take on how I should approach the job hunting process. At first, I was trying to listen to too many people at once, and as a result, I was not only overwhelmed from everything that was going on in my life, but I was also overwhelmed from all the advice I was getting. What works for one person may not work for you, and that’s totally okay. Do what makes sense for you and makes the job hunting process manageable for you. For me, this meant cutting back on the interviews I was scheduling each week. I know that people mean well when they give you unsolicited advice, but no one truly knows what you’re going through better than you do, and ultimately you know better about what works for you.

  4. Prioritize your mental health. Losing my source of income and my health insurance, processing the emotions from getting laid off, as well as dealing with the rejection that comes with the job hunting process, took a toll on my mental health. At first I was interviewing too much and not giving myself enough space to continue to pursue my hobbies or doing things that make me happy. Later, I realized I had to cut back on interviews so I could protect my happiness and mental health, and make time to do things that would bring me joy during this difficult time.

  5. Have a strategic approach for the companies/roles that you apply to. At first, I didn’t have a strategy other than to apply to any role that fit my skill set at companies I was familiar with/really liked. Later, I realized the interview process was very important to me since I’m primarily self-taught, and live coding/whiteboarding interviews have always been tough for me. I ended up applying to companies that had tech screens that catered to my strengths while spending some of my free time working on LeetCode problems and studying CS so that I could move back to live coding/whiteboarding interviews in the future.

  6. You can negotiate your severance. I had no idea you could negotiate your severance, so I just signed off on what was offered to me. If I could go back, I would have tried to negotiate, although the layoff my company did was one where there probably wasn’t much room for negotiation since so many people were laid off.

  7. Listen to your gut. When you no longer have a job, it’s easy to feel desperate and feel like you should accept the first offer you get. If you’re financially able to hold off on doing that, I’d recommend waiting until you get an offer that excites you. I had a couple potential offers in the beginning of my search, but I wasn’t excited about them at all. And I think that’s definitely a red flag – you don’t want to start working for a company if off the bat you have some resentment about the offer.

  8. Network and use social media to your advantage. I was able to get a lot of leads on possible job opportunities by reaching out to people who used to work at my previous companies. I was also getting a lot of help from strangers reaching out to me when I posted about getting laid off on LinkedIn.

Hopefully this is helpful for anyone else going through something similar. If you recently found a new job, congrats! If you’re still on the search for something new, good luck and hang in there!

How I went from being a Mid-Level Software Engineer to a Senior Software Engineer

My background in engineering isn’t the typical path – although what’s great about the tech industry is that I’ve met many software engineers who have nontraditional backgrounds as well. I studied painting and creative writing in school, and fell into coding when I had to put together a portfolio site for my artwork for a class. I taught myself the basics of HTML, CSS, and JavaScript. And since then, I’ve been hooked – I like how coding is it’s own art form. I like how I get to build things and solve complex problems.

So how did I go from being an Art/English Major to a Software Engineer, and then a Senior Software Engineer? After college, I held a number of web-related roles where I picked up different languages like Ruby and Python. The common thread in all my roles was that I was working with JavaScript in one form or another. I worked for a few nonprofits before I ventured over to working for startups. While working at one nonprofit, I took several night classes in web development (frontend development, backend development, and JavaScript development) before taking a couple months of leave to go through a web development immersive program. Although I was self taught up until that point, I wanted to ensure I hadn’t picked up any bad habits while working on small teams where I was usually the only one that did the type of work I do. After the program, I continued to work on learning as much as I could outside of work.

While working at a startup, I started to approach my work in a different way. I kept an eye out for ways I could improve my team’s process through automation. I would often propose feature work outside of the requests my team was getting, so that I could build out improvements that would automate our workflow. I noticed patterns in the repetition of the requests we were receiving and thought about how we could move away from a more manual process to an automated one. And through automation, I was able to cut down the number of requests my team had to handle manually from about 20+ a day to about 2 or 3 a week (sometimes we wouldn’t get any requests at all). This allowed my team to shift our focus to other products and merge with a different team within the company.

Aside from automation, I also looked for ways to help my fellow engineers. If I noticed that any of less experienced engineers were struggling with a language or process, I’d either look into a tool that could automate the process, or sometimes I’d create documentation to serve as a cheatsheet. When I was working on a team of primarily frontend engineers, and a couple of the less experienced engineers were overwhelmed by the command line or working with Ruby, I compiled a list of handy commands to make their lives easier. And whenever I ran into any issues with local development, I’d share any solutions I found with the team to ensure no one else would run into the same blockers. I also made myself available for pairing to help out other team members whenever they were blocked. And by finding solutions to bottlenecks in our processes via automation or tooling, as well as mentoring others, I got promoted to Senior Software Engineer.