Notes

Atom Feed

Website Image Tags

November 1, 2026

Image tags and sizes used for link previews, favicons, and app icons. Platforms change these limits without much notice, and some are not officially documented; these were last checked in November 2026. Values marked with * are from memory or third-party sources, and other values may also rely on secondary sources.

Recommended

This set covers link previews, browser tabs, search results, and home screens on current platforms:

File Size Used for
preview.png 1200x630 Large link previews on social and chat apps
favicon.ico 32x32 Older browsers and automated tools
icon.svg Scalable Browser tabs
apple-touch-icon.png 180x180 iOS home screen
icon-192.png 192x192 Android home screen
icon-512.png 512x512 Progressive web app install
icon-maskable-512.png 512x512 Android adaptive icons
<meta property="og:image" content="https://example.com/preview.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Description of the image">
<meta name="twitter:card" content="summary_large_image">

<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="manifest" href="/manifest.webmanifest">

The icons section of manifest.webmanifest is below; web app install also needs name or short_name, start_url, and display:

{
  "icons": [
    {"src": "/icon-192.png", "type": "image/png", "sizes": "192x192"},
    {"src": "/icon-512.png", "type": "image/png", "sizes": "512x512"},
    {"src": "/icon-maskable-512.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable"}
  ]
}

The 1200x630 image suits pages with a designed preview image, and fills the width of a message in chat apps. If the only image is a logo or icon, use a 280x280 square image instead so it appears as a small thumbnail next to the title, set the og:image:width and og:image:height tags to match, and use twitter:card summary. Do not reuse the 512x512 app icon for previews, since WhatsApp will show it at full size.

  • Use absolute https:// URLs for preview images
  • Use PNG or JPEG for preview images, and keep important content centered in case of cropping
  • Keep preview images under 600 KB, which is WhatsApp’s documented limit
  • Serve favicon.ico from the site root, since some tools only look there
  • Give the Apple touch icon an opaque background and square corners
  • Keep the logo in a maskable icon inside a centered circle with a radius of 40% of the icon width
  • sizes="32x32" reportedly stops Chrome from preferring the ICO over the SVG
  • Change the filename when replacing an image, since platforms and browsers cache them aggressively

Exhaustive

Link Previews

Tag Used by Size Aspect ratio File limit
og:image Facebook 1200x630 (600x315 for large, 200x200 minimum) 1.91:1 8 MB
og:image LinkedIn 1200x627 minimum 1.91:1 5 MB
og:image WhatsApp 300 pixels wide or more for large 4:1 or narrower 600 KB
og:image Discord 1200x630 in Discord’s example; no size requirement Undocumented Undocumented
og:image Signal Any size meeting the rules below; 1200x630 and 280x280 work See the rules below Undocumented
og:image Slack, iMessage, others 1200x630 for large*, 280x280 for thumbnail* 1.91:1 for large*, 1:1 for thumbnail* Undocumented
twitter:image (summary_large_image) X/Twitter 1200x600* (300x157 minimum*, 4096x4096 maximum*) 2:1* 5 MB*
twitter:image (summary) X/Twitter 400x400* (144x144 minimum*) 1:1* 5 MB*

X falls back to og:image when twitter:image is missing, but needs twitter:card to choose the card format.* X accepts JPG, PNG, WEBP, and GIF, and only uses the first frame of an animated GIF.*

Chat apps choose between a large preview and a small thumbnail using either the image’s dimensions or the page’s tags:

App Large preview when Source
Discord twitter:card is summary_large_image Documentation
WhatsApp At least 300 pixels wide, 4:1 or narrower, and under 600 KB Documentation
Slack About 400 pixels wide or more One contributor’s report, not documented
Signal Desktop Width and height are at least 200 pixels, and not within 5% of square Source code
Signal Android Width is at least 150dp in device pixels, and wider than tall Source code
Signal iOS Width is at least about 2x the maximum message width, and height is at least 33% of that Source code

WhatsApp documents the requirements for a large preview, and says it may relax them or revert to small previews without giving a threshold, so a thumbnail under 300 pixels wide comes from the same report. Signal does not use a single width threshold, so a large square image may still appear as a thumbnail. Discord shows a small image beside the text by default, accepts PNG, GIF, JPEG, WEBP, and AVIF, and fetches the image to measure it unless og:image:width and og:image:height are set.

Preview Image Properties

Tag Meaning
og:image:url Same as og:image
og:image:secure_url HTTPS alternate URL
og:image:type MIME type
og:image:width Width in pixels
og:image:height Height in pixels
og:image:alt Description of the image
twitter:image:alt Description of the image, 420 characters maximum*

Structured Data

Tag Used by Size Aspect ratio
JSON-LD image on an Article Google Search Width x height of at least 50,000 pixels Provide 16:9, 4:3, and 1:1
<meta itemprop="image"> Schema.org microdata consumers Same as og:image* 1.91:1*

Favicons

Tag Size Used by
<link rel="icon" type="image/svg+xml"> Scalable Modern browsers, including Safari 26 and later
<link rel="icon" type="image/png"> 16x16*, 32x32* Browser tabs
<link rel="icon"> or /favicon.ico 16x16*, 32x32*, 48x48* Older browsers and automated tools
<link rel="icon"> Square, above 48x48 (8x8 minimum) Google Search results
<link rel="shortcut icon"> Same as icon Older alternative to icon

App Icons

Tag Size Used by
<link rel="apple-touch-icon"> 180x180 Current iPhones*
<link rel="apple-touch-icon"> 167x167 iPad Pro*
<link rel="apple-touch-icon"> 152x152 iPad*
<link rel="apple-touch-icon"> 57x57*, 60x60*, 72x72*, 76x76*, 114x114*, 120x120*, 144x144* Older iOS devices
/apple-touch-icon.png 180x180 Safari, without a <link> tag
Web manifest icons 192x192, 512x512 Android, web app install
Web manifest icons with maskable 512x512 Android adaptive icons

Legacy

These are safe to skip on new sites:

Tag Size Used by
<link rel="image_src"> Same as og:image* Older scrapers*
twitter:image:src Same as twitter:image* Older name for twitter:image*
<link rel="apple-touch-icon-precomposed"> Same as apple-touch-icon* iOS 6 and earlier
<link rel="mask-icon"> Scalable, single color SVG Safari pinned tabs before Safari 12*
<meta name="msapplication-TileImage"> 144x144* Windows 8 tiles*
browserconfig.xml 70x70*, 150x150*, 310x150*, 310x310* Windows 8.1 and 10 tiles*

Sources:

Permalink

Timezone Boundaries Mapped

September 25, 2026

The IANA timezone database contains over 400 timezone entries mostly named as “<continent>/<city>”. They are meticulously cataloged to group regions of the world not only by UTC offset but also by the presence and timing of Daylight Savings as well as current and historical timezone policy changes.

The github.com/albertyw/localtimezone repository maps latitude/longitude data to IANA timezone names. It is based on github.com/evansiroky/timezone-boundary-builder which in term is based on OpenStreetMap. From that data, I generated an Interactive Map:

Timezone Map

Permalink

Comparing WebdriverIO Firefox vs Chrome

September 5, 2026

Chrome recently started releasing arm64 linux builds which meant that my ubuntu-on-m1-mac can run webdriverio (wdio) builds on both firefox and chrome (it was previously stuck doing only firefox builds).

I therefore compared build speed of codemancer on firefox versus chrome.

wdio.conf.ts Configuration

Firefox:

capabilities: [{
  maxInstances: 5,
  browserName: 'firefox',
  'moz:firefoxOptions': {
    args: ['-headless'],
  },
  acceptInsecureCerts: true,
}],

Chrome:

capabilities: [{
  maxInstances: 5,
  browserName: 'chrome',
  'goog:chromeOptions': {
    args: ['--headless=new', '--no-sandbox', '--disable-dev-shm-usage', '--disable-gpu'],
  },
  acceptInsecureCerts: true,
}],

For Arm architectures, the most recent version of wdio still depends on @puppeteer/browsers at ^2.2.0 which doesn’t correctly fetch Chrome’s Arm builds. Therefore, these additional configs need to be added to wdio.conf.ts:

// Set these environment variables to manually-downloaded chrome executables
// For the satantime/puppeteer-node:26-trixie-slim docker images, use
// CHROME_BINARY=/usr/bin/chromium
// CHROMEDRIVER_BINARY=/usr/bin/chromedriver
const chromeBinary = process.env.CHROME_BINARY;
const chromedriverBinary = process.env.CHROMEDRIVER_BINARY;

// inside capabilities
'goog:chromeOptions': {
  args: [/* ... */],
  ...(chromeBinary ? { binary: chromeBinary } : {}),
},
...(chromedriverBinary ? { 'wdio:chromedriverOptions': { binary: chromedriverBinary } } : {}),

Benchmarks

I benchmarked both browsers on codemancer unit tests over 30 iterations.

On Arm64, Chromium 151 against Firefox 155:

browser    runs      min   median     mean      max
chrome       10   4934ms   6593ms   7143ms   10054ms
firefox      10   7055ms  11426ms  17360ms   50600ms

On x86_64, Chromium 152 against Firefox ESR 140:

browser    runs      min   median     mean      max
chrome       10   4433ms   5265ms   6798ms   15222ms
firefox      10   6645ms   9119ms  18613ms   56509ms

References

Permalink

Geolocation Precision

July 4, 2026

Latitude/longitude and other geolocation systems can express a position at exponentially increasing precision as you add digits or levels. Below are tables of the approximate ground precision of several coordinate systems.

One degree of latitude is roughly constant everywhere (~111 km), but one degree of longitude shrinks toward the poles as the meridians converge, scaling with the cosine of the latitude. For the latitude/longitude systems below, the east/west distance is therefore given at several latitudes. Grid systems like H3, S2, Geohash, and Plus Codes are designed to be nearly uniform across the globe, so their precision is instead given as an approximate cell edge length and area.

Degrees with decimals (Degrees)

Degrees Decimals E/W at equator E/W at 20° N/S E/W at 45° N/S E/W at 70° N/S
1 0 111.3 km 104.6 km 78.72 km 38.07 km
0.1 1 11.13 km 10.46 km 7.872 km 3.807 km
0.01 2 1.113 km 1.046 km 787.2 m 380.7 m
0.001 3 111.3 m 104.6 m 78.72 m 38.07 m
0.0001 4 11.13 m 10.46 m 7.872 m 3.807 m
0.00001 5 1.113 m 1.046 m 78.7 cm 38.1 cm

Degrees-minutes-seconds (DMS)

Precision Unit E/W at equator E/W at 20° N/S E/W at 45° N/S E/W at 70° N/S
1°00′00″ degree 111.3 km 104.6 km 78.72 km 38.07 km
0°01′00″ arcminute 1.855 km 1.743 km 1.312 km 634.6 m
0°00′01″ arcsecond 30.92 m 29.06 m 21.87 m 10.58 m
0°00′00.1″ 0.1 arcsecond 3.092 m 2.906 m 2.187 m 1.058 m
0°00′00.01″ 0.01 arcsecond 30.9 cm 29.1 cm 21.9 cm 10.6 cm

Geohash (base32)

Each geohash character adds 5 bits, alternating between longitude and latitude, so cells are square at odd lengths and 2:1 (wider than tall) at even lengths.

Length Cell size (lng × lat) Ground size at equator
1 45° × 45° 5,009 km × 5,009 km
2 11.25° × 5.625° 1,252 km × 626.2 km
3 1.406° × 1.406° 156.5 km × 156.5 km
4 0.3516° × 0.1758° 39.14 km × 19.57 km
5 0.04395° × 0.04395° 4.892 km × 4.892 km
6 0.01099° × 0.005493° 1.223 km × 611.5 m
7 0.001373° × 0.001373° 152.9 m × 152.9 m
8 0.0003433° × 0.0001717° 38.22 m × 19.11 m
9 0.00004292° × 0.00004292° 4.777 m × 4.777 m

Plus Codes (Open Location Code)

Code length Cell size Ground size at equator
2 20° 2,226 km
4 1° 111.3 km
6 0.05° 5.566 km
8 0.0025° 278.3 m
10 0.000125° 13.92 m
11 0.000025° 2.783 m
12 0.000005° 55.7 cm

H3 hexagonal geospatial indexing

Resolution Avg edge length Avg cell area
0 1,281 km 4,357,449 km²
1 483 km 609,788 km²
2 183 km 86,802 km²
3 68.98 km 12,393 km²
4 26.07 km 1,770 km²
5 9.854 km 253 km²
6 3.725 km 36.13 km²
7 1.406 km 5.161 km²
8 531.4 m 0.7373 km²
9 200.8 m 0.1053 km²
10 75.86 m 0.01505 km²
11 28.66 m 2,150 m²
12 10.83 m 307 m²
13 4.092 m 43.9 m²
14 1.546 m 6.27 m²
15 58.4 cm 0.895 m²

S2

Level Avg edge length Avg cell area
0 7,842 km 85,011,012 km²
4 490 km 332,074 km²
8 30.63 km 1,297 km²
10 7.658 km 81.07 km²
12 1.915 km 5.067 km²
16 119.7 m 0.0198 km²
20 7.479 m 77.3 m²
24 46.7 cm 0.302 m²
28 2.92 cm 11.8 cm²
30 7.3 mm 0.737 cm²

UTM (Universal Transverse Mercator)

UTM projects each of 60 longitudinal zones (each 6° wide) onto a flat grid and expresses a position as an easting/northing in meters within the zone. Because the coordinate is already metric, the precision is simply how many digits of the easting/northing you keep.

Easting/northing digits Rounded to Ground precision
550__ 10 km 10 km
5502_ 1 km 1 km
55020 100 m 100 m
550200 10 m 10 m
5502001 1 m 1 m
5502001.0 0.1 m 10 cm

MGRS (Military Grid Reference System)

MGRS is a grid-based alphanumeric encoding built on UTM (and UPS at the poles): a grid-zone designator, a 100 km square identifier, then equal numbers of easting and northing digits. Each added digit pair narrows the cell tenfold.

Digits (per axis) Example Ground precision
0 10SEG 100 km
1 10SEG12 10 km
2 10SEG1234 1 km
3 10SEG123456 100 m
4 10SEG12345678 10 m
5 10SEG1234567890 1 m

Maidenhead locator system

Used by amateur-radio operators, Maidenhead alternates letter and number pairs (field → square → subsquare → …) to encode longitude and latitude. Cells are 2:1, wider than tall, because longitude spans 360° against latitude’s 180°.

Characters Cell size (lng × lat) Ground size at equator
2 (field) 20° × 10° 2,226 km × 1,113 km
4 (square) 2° × 1° 223 km × 111 km
6 (subsquare) 5′ × 2.5′ 9.277 km × 4.638 km
8 (extended) 30″ × 15″ 927.7 m × 463.8 m
10 1.25″ × 0.625″ 38.65 m × 19.33 m

Permalink

Interpreting Linux Memory Metrics

May 25, 2026

note

Linux memory accounting is full of metrics that look similar but measure very different things. This post is a short tour of the most useful ones and where they come from.

How Linux Models Memory

Linux gives every process a private virtual address space. Pages in that space may or may not be backed by physical RAM at any given moment - the kernel pages them in on demand and evicts them under pressure. Many pages are also shared between processes (libraries, the page cache, copy-on-write forks), so “how much memory does this process use?” does not have a single right answer. It depends on whether you count what is reserved, what is resident, what is private, and how shared pages are split across processes.

On top of that, the kernel itself uses memory for the page cache, slab allocators, buffers, and reclaimable structures. “Free” memory is rarely the number you actually care about, because the kernel will happily use almost all RAM for cache and return it on demand.

Per-Process Metrics

From /proc/<pid>:

  • VSZ (Virtual Size): Total size of the process’s virtual address space, including code, data, mapped files, and unallocated reservations. Pages that are mapped but never touched still count. Useful as an upper bound, not as a usage number.
  • RSS (Resident Set Size): Amount of physical RAM currently backing the process’s pages. Shared pages are counted in full for every process that maps them, so summing RSS across processes overcounts system memory.
  • PSS (Proportional Set Size): Like RSS, but each shared page is divided by the number of processes sharing it. Summing PSS across all processes approximates total physical memory in use.
  • USS (Unique Set Size): Private resident memory only - the portion that would actually be freed if the process exited. The truest measure of a process’s incremental cost.
  • WSS (Working Set Size): The set of pages a process actively touches over a given time window. This is the minimum RAM the process needs to run without thrashing. Not a static counter; tools like wss.pl sample idle/young page flags to estimate it.
  • Swap: Pages that have been pushed out to a swap device. Visible per-process in /proc/<pid>/status (VmSwap) and smaps.

System-Wide Metrics

From /proc/meminfo:

  • MemTotal / MemFree: Total RAM and the small slice that is completely unused. MemFree is almost always misleadingly low on a healthy system.
  • MemAvailable: Kernel’s estimate of how much memory is available for new allocations without swapping, accounting for reclaimable cache and slab. This is the field to watch.
  • Buffers / Cached: Page cache used for block devices and file contents. Reclaimable on demand.
  • SwapTotal / SwapFree: Swap device capacity and remaining space.
  • Dirty / Writeback: Pages modified in cache that still need to be flushed to disk. Spikes here can stall writes.

Pressure and Reclaim

Raw “used vs free” numbers do not tell you whether the system is struggling. Two further signals do:

  • PSI (Pressure Stall Information): Exposed at /proc/pressure/memory and per-cgroup at memory.pressure since kernel 4.20. Reports the percentage of wall time over 10s/60s/300s windows during which some tasks (some) or all tasks (full) were stalled waiting on memory reclaim. Even small non-zero values indicate the system is doing real work to find memory.
  • pgscan / pgsteal / pgmajfault in /proc/vmstat: Counters for how aggressively the kernel is scanning the LRU lists, reclaiming pages, and servicing major faults from disk. Rising rates here usually precede visible slowdowns.
  • pswpin / pswpout in /proc/vmstat: Pages swapped in from and out to disk. Non-zero pswpin means the system is paying real disk I/O to bring previously-evicted pages back into RAM - a direct indicator that the working set no longer fits.

When to Use Which

  • Capacity planning for a single process: USS for incremental cost, WSS for the RAM it actually needs to run without thrashing.
  • Adding up processes to explain total RAM: PSS. RSS double-counts shared libraries; USS undercounts them.
  • Sizing a container or cgroup memory limit: WSS plus headroom for the page cache the workload depends on. Setting the limit at RSS is a common cause of surprise OOM kills.
  • “Is the box about to OOM?": MemAvailable trending down plus PSI memory.full above zero. MemFree alone will mislead you.
  • Investigating a slowdown that “has plenty of free memory": PSI, pgscan, pgmajfault, and Dirty/Writeback. High scan rates with low fault rates mean the kernel is working to keep up; high major-fault rates mean it is losing.
  • Diagnosing a memory leak in a long-running process: watch RSS and USS over time. Rising USS is a real leak; rising RSS with flat USS is usually shared-library or cache growth.
  • Comparing two processes that load the same big library: USS, since RSS will charge each one the full library cost.
  • Deciding whether to add swap: SwapFree trending toward zero combined with non-trivial PSI memory.some means the system is already paging under pressure.
  • Tuning a database or file server: Cached and Buffers should be large - that is the page cache doing its job. Worry when Dirty spikes or Writeback stays elevated.
  • Choosing what to alert on in production: MemAvailable, PSI memory.full avg60, and swap-in rate (pswpin in vmstat). These three together catch nearly every memory-related incident before users do.

Further Reading

Permalink

Coordinate to Timezone Lookup Library

April 5, 2026

Go Compression Benchmark Results

March 19, 2026

California Oak Tree Identification

February 7, 2026

Claude Code With Ollama Setup

January 31, 2026

Switching From Python requirements.txt to pyproject.toml

December 6, 2025

Generating Cloudflare Origin Certificate for Multiple Domains

November 8, 2025

Introductory Computer Science and Software Engineering Topics

August 3, 2025

PID Controller

June 29, 2025

Availability Percentages

February 8, 2025

Javascript/Typescript Decorators Suck

January 3, 2025

Upgrading MariaDB Database Versions

June 2, 2024

Concurrent Python Example

January 1, 2024

Updating UUIDField on MariaDB to Django 5

December 27, 2023

Replacing Setup.py

December 7, 2023

Fixing Mariadb --Column-Statistics Errors

June 5, 2023

Geographic Geometry Simplification

February 2, 2023

Linters

January 2, 2023

Installing Mysqlclient in Python Slim Docker Image

December 29, 2022

Processor Trends

December 19, 2022

Resizing a Ubuntu Disk in a UTM VM

October 19, 2022

Bash File Test Operators

October 5, 2022

Python Generic Type Annotations

May 28, 2022

Mac Menubar Applications

February 17, 2022

Logodust

February 13, 2022

Python Releases

January 8, 2022

Debian Releases

January 7, 2022

Ubuntu Releases and Support Periods

December 18, 2021

Monitoring System CLIs (Top for X)

December 18, 2021

Fixing "EFI stub: Exiting boot services and installing virtual address map..."

December 11, 2021

ARM Support

November 29, 2021

Map Caps Lock to Escape for Vim

November 24, 2021

Download and Convert Youtube Playlists to MP3 Files

July 15, 2021

Nobody Ever Got Fired for Copying FAANG

June 27, 2021

Removing Token Authentication From Jupyter/iPython Notebooks

May 31, 2021

Debian and Ubuntu Releases

February 13, 2021

Setting Up FastAI Fastbook on a Fresh Ubuntu Instance

January 31, 2021

Tip for Developer Tools Startups

January 30, 2021

A Better Go Defer

October 20, 2020

Covid-19 Economy Predictions

October 13, 2020

Basic Docker Monitoring

July 4, 2020

Switching From Go Dep to Go Mod

May 30, 2020

Upgrading LibMySQLClient in Python MySQLDB/MySQLClient

May 25, 2020

Developing Django in Production

May 15, 2020

Quote

March 5, 2020

Sendmail Wrapper for Mailgun

March 1, 2020

Python Release Support Timeline

December 26, 2019

Use the Default Flake8 Ignores

December 14, 2019

Making Pip Require a Virtualenv

December 5, 2019

Engineering Toolbox

November 30, 2019

Node Timezones

November 1, 2019

Sampling Samples

August 21, 2019

Rotating a NxN Matrix in One Line of Python

July 27, 2019

iTerm2 Search History

July 19, 2019

Nginx Auth With IP Whitelists

June 29, 2019

Bash Strict Mode

May 11, 2019

Optimizing Asus Routers for Serving Websites With Cloudflare

May 5, 2019

Browserify, Mochify, Nyc, Envify, and Dotenv

April 1, 2019

Scraping Images From Tumblr

February 24, 2019

There Are Too Many NPM Packages

February 10, 2019

Programmers Writing Legal Documents

January 31, 2019

Solidity Review

November 17, 2018

Likwid

November 9, 2018

My First Server's IP

November 9, 2018

Installing Netdata

September 23, 2018

Interrobang Versus Shebang

July 10, 2018

Bad Interview Questions

July 8, 2018

Showing Users in Different Databases

July 7, 2018

Some MIT (Undergraduate) Admissions Interview Advice

July 4, 2018

Optimize the Develop-Test-Debug Cycle

April 22, 2018

Example of Python Subprocess

March 23, 2018

Spotted in Taiwan

January 20, 2018

Fixing "Fatal Error: Python.h: No Such File or Directory"

December 16, 2017

Cassandra Primary Keys

December 11, 2017

MyPy Review

November 2, 2017

Griping About Time Zones

October 26, 2017

Bundling Python Packages With PyInstaller and Requests

September 23, 2017

Go Receiver Pointers vs. Values

September 4, 2017

Fixing statsonice.com Latency

September 1, 2017

Showing Schemas in Different Databases

August 26, 2017

Straight Lines

June 2, 2017

Emerson on Intellect

May 29, 2017

Core Metric for Developer Productivity

May 21, 2017

How to Capture a Camera Image With Python

May 7, 2017

Python Has a Ridiculous Number of Inotify Implementations

May 2, 2017

Projects: Gentle-Alerts

April 27, 2017

Creating a New PyPI Release

April 24, 2017

Eva Air USB Ports

April 24, 2017

Projects: Git-Browse

March 18, 2017

Cassandra Compaction Strategies

March 5, 2017

Code Is Like Tissue Paper

January 25, 2017

Seen in a Bathroom Stall at MIT

January 24, 2017

Underused Python Package: Webbrowser

January 21, 2017

Pax ?

January 5, 2017

Golang Review

January 2, 2017

Wadler's Law

December 15, 2016

Tunnel V2

December 8, 2016

MultiPens

December 5, 2016

SSH Tunnel

September 18, 2016

That Time I Was a Whitehat Hacker

September 18, 2016

Comparison of Country and Company GDPs

September 8, 2016

Sketching Science

September 8, 2016

Tech Hiring Misperceptions at Different Companies

July 22, 2016

Calculating Rails Database Connections

June 26, 2016

DevOps Reactions

June 12, 2016

Tuning Postgres

June 9, 2016

Fibonaccoli

June 4, 2016