Source: Goat Rock Beach, from Wikipedia

I've had a few opportunities to learn that I definitely shouldn't read comments about me (or anything really) on the Internet, but sometimes morbid curiosity gets the better of me. Firmly not learning from the past, I found myself sifting through a hundred or so of these Internet comments earlier today. The general consensus seemed to be that I'm wasting my life and I'm wrong for living in a truck.

But that really confused me, because I don't live in a truck.

You wanna know where I live?

I live at Goat Rock, where I went outdoor rock climbing for the first time today with a few friends. I watched deer dart back and forth across a hillside while I was hanging from a boulder, slicing my hands sliding against rough rocks.

I live on a hundred miles of biking trails, sometimes for hours at a time. I ride along highways and over bridges and beside marshes and anywhere that my bike is willing to take me. Sometimes I don't even know where I want to end up.

I live at the Shoreline Amphitheatre, and the Fox Theatre, The Independent, The Regency Ballroom, and half a dozen other random venues, where I dance around like an idiot and belt my heart out to my favorite bands.

I live on a picnic blanket in a bunch of different local parks, where my girlfriend and I take turns reading The Martian to each other and playing fetch with her tiny, adorable dog.

I live at the gym, because I always want to be healthier and stronger and faster, and I'm at my happiest when I'm improving.

I live in a handful of small coffee shops, where I hack away at a hundred different side projects and read because life is too short to not know stuff.

I just sleep in a truck. Living is what happens when you wake up.

Source: Truck clipart forever from Clker, bathroom stick peeps from ClipArtBest

I feel like it's been a while since I started a new series of posts. Sure, we've got Truck Tech and Home Improvement and Tips from the Truck and Q & A, but I'm pretty confident we have room for at least one more. If titles weren't supposed to be short, I'd probably extend the series name to: Incredibly Obvious Facts About Box Trucks (And Their Implications), just so we're all definitely on the same page. Anyway, these posts will be all about inherent properties of box trucks, and what that means for how I structure and live my life. Our first patently obvious fact about box trucks: they definitely don't have bathrooms.

To illustrate the above obvious fact, here's a recent* picture of the box.

Not a single bathroom in sight.

Box trucks are well-suited to a wide range of activities. Need to make an area more sketchy? Park a box truck there and watch the surrounding property values plummet.** Worried you don't own enough things covered in graffiti? Buy a box truck, they're magnets for impromptu community art sessions. Got some stuff to move? I know seven satisfied customers who can testify that Brandon's Ad Hoc Moving Service™ comes in handy on occasion. Box trucks are great for hauling crap around…just not in the literal sense.

Which brings us back to the (decidedly unglamorous) topic at hand: my home of choice doesn't have a bathroom. But what does that mean? Well, I've already talked at length (arguably too much) about the implications of not having a nearby bathroom, so we'll gloss over that part. Basically, it's not a huge deal because I'm never in the truck except when I'm sleeping. It does change how I think about bathrooms though. It's not a room in my house where I keep my hygiene-related stuff. For me, it's any place where I can get myself ready for starting or ending a day. This is what my bathroom looks like:

Sure, there's no marble countertops or glass walls, but it gets the job done.

Or from a few other (equally unflattering) angles.

I own more Axe® products than a prepubescent boy preparing for his first date.
For the record, I'm neither of those things.

Uh Brandon, I know you're slowly losing your mind and all, but that's definitely a travel bag…not a bathroom.

Why not both? That bag has everything I need to not look/smell*** like I live in a truck, just add water. And really, it's hardly any less convenient than a personal bathroom would be. In fact, it's definitely got a few perks. For one, normal bathrooms are hands-down the worst part of a house to clean. Aside from the general uncleanliness that pervades bathrooms by their very nature, they also have that whole Portal to Hell™-area going on behind the toilet. When was the last time anyone willing stared into that abyss? Never. Seriously, that place is a straight-up war zone, with different gangs of bacteria and mold-like creatures fighting for turf. There are more unclassified species back there than in the Amazon. I'm downright joyful that I don't have to fight that battle.

That's not to say I'm just pawning off cleaning and making it someone else's problem though. I'm an ardent subscriber of the whole "Leave things better than you found them" philosophy, and always make sure to clean up after myself and then some. For example, and I'll never understand this, but for some reason people love to strew their gym towels haphazardly around the locker room on Friday nights. When I come in on Saturday morning, it looks like a washing machine projectile vomited all over the place. Or like a bomb went off in the laundry bin. In any case, I'll usually take a few of them and toss them in the actual towel receptacle (a mere three feet away) on my way out the door. It's certainly not the most heroic act ever committed, but it stops me from feeling like my questionable life choices are to the detriment of others.

The only (incredibly minor) downside is that no bathroom means no mirror, meaning the first time I see my ugly mug is after I've subjected everyone else to it at the gym. When I stroll into the gym with Beyoncé blaring, I quite literally "woke up like this".

*I've gotten rid of the wood, extra insulation, and tire since I took this photo. I also built the previously pictured coat rack for my shirts.

**Unfortunately, this doesn't work in the Bay Area.

***I don't know if the truck has a scent or not. If it does, it's certainly not the one I want to smell like.

Source: Question mark from Online Web Fonts, clock from ClipArt Best. Looking at this again, it would have made more sense to put the clock in the dot of the question mark…oh well.

As of me typing these words, my little truck experiment has been going on for over a year and four months. That's been more than enough time to see a thousand different questions fly through this site and my inbox, and every so often I'll sit down and answer a few of them. But there's one question that I haven't answered, and can't seem to escape. It's usually one of the first questions to come up in conversation, and half a bazillion variations of it are sitting in my queue:

How realistic is it to live in a truck for the next 10 years?

How long will you continue to live in the truck?

Are you going to use your savings to make a down payment on a house?

Are you comfortable living in a truck indefinitely?

You get the idea. Basically, people want to know when the hell I'm going to get my shenanigans together and be a normal, functioning member of society. Don't get me wrong, it's not that I've been avoiding the question, it's just that I've never had a good answer. Normally I'll say something like:

"Whenever the truck stops making sense."

Standing alone, that answer is pretty useless, and I definitely don't have enough of the Mr. Miyagi swagger to make it sound sagacious or insightful. But anyway, this post is all about figuring out just how truck-filled my future could be.

If you've been following along with my story disjointed ramblings for a little while, you probably have a pretty good sense by now that I have literally no idea what I'm doing. At all. Sure, I plan things out sometimes, but I hardly ever consider how to piece it all together. I'm just kinda playing things by ear: trying to live as simply as I can, attempting to figure out what I want out of life, and deciding what happiness means to me. So it's fair to say that I haven't put a ton of thought into a timeline for migrating out of the truck and into a more permanent crash pad. In my defense though, the actual "migrating out of the truck" part would take all of 10 minutes. But anyway, to figure out how long it makes sense to stay in the truck, let's go back to the beginning, to figure out how we even ended up here.


When I started this adventure, all I knew was that it didn't make a lot of sense for me to get an apartment. I'd spent a summer out here two years ago, and from that experience, I could confidently say that I'd rarely be home. Plus I consider traffic a form of torture and I'd rather spend my money building stupid things, like bike racks and my future. So this was the logical conclusion extreme, and I bit the bullet betting that this lifestyle would be simpler, without actually sacrificing my happiness or anything else I cared about. And I like to think it's paid off. So as weird as it is, the truck just made sense for me, given where my priorities were (and still are). There's not really an endgame; as long as my goals stay the same and the truck remains a valid tool for achieving them, I'll stick with it.

So... how long will that be?

If we're looking for a milestone that makes sense to stop with all this truck business, losing my go-to parking spot probably would have been as good a time as any to call it quits. Clearing out my student loans would have been a satisfying high-note to end on, and rounding out an entire year in the box would have worked too.

More recently, someone asked me how my retirement nest egg is doing, because the savings clock only shows how much money I'd have saved over a hypothetical apartment. Between the various retirement accounts, I just broke into six-figure territory a week or two ago (semi-independently confirmed by Mint). $100,000 is a nice round number, why not call it a day, drive my truck up to the city, and toss my bed and dresser into a respectable studio apartment? Hell, why not take those savings and put a down payment on a house? Why am I still spending my slumbers surrounded on six sides by an super-sized sardine can?

Well, because it still makes sense.

While a lot of stuff has changed over the past year, that hasn't. And if after two years, or five years, the truck still maintains all the properties that originally drew me to it, I'll still be here. It's weird though, because on the other hand, there's actually very little that keeps me from abandoning it at any given second. For example, if I went back and found some huge hairy mutant spider in the truck tonight, there's a 96.4% chance I'd never sleep in it again.

Or maybe I'll go back one night and find it burned to the ground in some freak accident. I honestly don't even think it'd be a big deal. I mean, what would I really be losing? A bed and a week's worth of clothes? Hardly worth ruining a perfectly good day over.

But let's assume for a second that the mutant spiders only come out while I'm sleeping, and the truck doesn't burst into flames on a whim. What do I think the plan will look like?

The Closest Thing to a Plan

There's always this implicit assumption in every question about my future plans: that I'll be moving into an apartment/house at some point. But, if everything goes to plan, it'll be the exact opposite. I've talked pretty seriously about spending the rest of my life traveling, so let's take that as a given and see where we're at.

Through that lens, the truck feels more like a stepping stone, a transition phase. In the same way that college is a transition from living at home to living in the real worldideally, the truck is a transition from living in a singular, fixed place to living everywhere…and nowhere at all. Becoming sufficiently comfortable with the truck, my next home will ideally be nothing more than a backpack. I'll hop around the world as passports and seasons and retirement monies allow, staying in hostels and exploring the places that words in my travel books couldn't possibly do justice.

So long story short, I don't know how long the truck will be a part of my life, but I'll enjoy it while it lasts.

Source: My actual "closet", aka a pipe bolted across the back of the truck. And it only took me 6 months to finish.

It's that time again, when I realize that I've been neglecting people's questions for too long and they've reached a critical mass. It's time to clean out the closet. Not the literal one pictured above, though I should probably do a write up for how I threw that together too.

I just read your leather strap solution to your drawer problem. Have you considered magnets?

Indeed I had, and in fact I use some neodymium magnets to hold a makeshift screen onto my sunroof. I decided against using magnets on the dresser drawers because of their force characteristics. Basically, I didn't like the idea that I'd have to Goldilocks my way to the right strength of magnet: too weak and the drawers do as they please when I take turns, too strong and they become difficult to open, not to mention they might rip the super glue off instead of simply separating. Snaps and straps are much easier to reason about: I snap them closed and the drawers don't move, I unsnap them and I can get at my clothes freely, without a fight.

I'd like to see a widget on the site that provides the current temperature inside the box. Or perhaps a temperature readout associated with the posts you make while inside the box. Basically, interested to see the temperature range and what the temperature drops to overnight in the winter.

That would be an interesting project. Get a little solar panel, a Raspberry Pi or Arduino, temperature sensor, and cell modem, and POST some data to the site every few minutes. I mean, I'm not going to actually do it, but I agree, it'd be interesting. How about a pretty good approximation though? The box truck may very well be an oven during the day, but I'm only ever in it at night, and the truck has basically zero functional insulation. At night, the temperature outside is the temperature inside, with maybe a degree or two difference, so checking the weather in South Bay will let you know how the box is doin'. To keep warm in "winter", I usually just pull a blanket or two over and that does the trick. I put winter in quotes because, as someone from a place with actual seasons, what happens in the Bay Area hardly qualifies.

Is physical address verification required for mailbox renewal?

You know, I really can't remember. I don't think so. Every six months when I go to renew my private mailbox, I swipe my card and that's usually the end of it. When I initially got the mailbox, there were definitely things to read and papers to sign, but I don't think I had to verify any other addresses, just provide a previous one.

You've talked about retiring and retiring early, so clearly the future is on your mind. Are you considering having a family ever/are your calculations based on providing for you alone?

This is a great question, even though the future is scary and I act like a small child. My ramblings at the end of this post explain it more thoroughly, but my strategy for the future is just to create as many opportunities for myself now, so that when the time comes to make Serious Adult Decisions™ (or SAD, for short), I have the flexibility to do what I want. You're right, my early retirement math gets a lot easier when it's just me, but I'm also not naïve enough to think that I know what I'll be like ten years from now. Do I want kids? Who knows. No doubt, there's certainly something attractive about the idea of tiny genetic hybrids of you and someone you think is awesome. That said, I'm fortunate enough to have the luxury of not needing to decide if that's what I want right now. One thing I'll say is that if I did "settle down", I highly doubt future-me would accept the traditional way of doing it. I'm not saying there'd be trucks involved, but there'd definitely still be a whole lot of travelling and something resembling retirement.

Can you please elude to your eating habits? Do you have a small kitchen, grill, mini fridge in the box? Are you going out to eat more often? Lastly, monthly food expense (approx), thanks!

The truck has zero kitchens, grills, and/or mini-fridges. In fact, the truck has zero anythings that aren't beds and/or dressers. I eat three square meals a day at work, and I go out on the weekends. I spend $50-75 a weekend on food, so probably ~$300/month. My diet consists of copious amounts of chicken, with some veggies thrown in for decoration.

Any plans to fix up the inside, like removing the garage door and putting in a wall with a camper-style door…or anything for the walls? It's looking pretty grim in there, man.

I've considered putting in drywall or replacing the rear gate, but I invariably end up asking myself the same question: why? Let's be honest with ourselves here, no amount of drywall or renovation is going to make up for the fact that it's a sketchy old moving van. I can put a new coat of paint on it, I can redo the floors in beautifully-finished hardwood, I can hang up paintings—you get the idea, but it'll still be the same truck. Something something lipstick on a pig. I chose the truck because I was indifferent to appearances and all I needed was a bed and a place to store my clothes. Everything else is superfluous. If I cared about how grim it looked or what people thought of it, it's unlikely I'd have ever gotten a truck (or even an RV) in the first place. The truck serves its function and it serves it well, so it's hard to justify putting in the money, time, and effort to make any "improvements" which do nothing to make me a happier, healthier person.

Thoughts on something like an RV park?

I very briefly looked into it after my unceremonious (but not unexpected or unwarranted) eviction. The conclusion I came to is that no RV park would want me and my MacGyver'd shanty. As it stands, the truck doesn't have much in common with an RV: it doesn't have electricity, water, or the hookups to provide them. Even if a particularly open-minded RV park was willing to take me under their wing, it'd likely be a non-zero distance from my work, negating all of my nice commuting benefits.

And that's all for this episode of Questions and Answers. As always, keep the questions, curiosities, and whatever else crosses your consciousness coming.

Source: Amalgamated from Jim Browne Chevy and Bob 'n' Bee. Basically, I took a way nicer, newer version of my truck and Photoshopped someone else's mail icon onto it.

I've gotten into this wonderful rhythm of publishing posts that are tragically untimely. My Spring Cleaning post was five days too late, I'd had the insulation and skylight for weeks before I'd recounted the tale, and I'd successfully picked up and put down my weight goals way before I picked up the pen and put down a post. So it's only fitting that I'm just getting around to talking about a feature I added to the site over eight months ago.

Every so often, I get bored and fidgety and change things around on the site. Sometimes I'll tweak the savings calculation, sometimes I'll move around items on the mobile layout, and yet other times I'll sit down with a coffee and some music and plop a few new features into existence. The title and picture probably provide plenty perspective, but this time around, I added email subscriptions. I noted in this post (a relative eternity ago) that I was thinking about adding them because, in theory, it's pretty simple. Someone gives me their email address and clicks a button, then they get an email every time I write a new post. Unfortunately, like pretty much every problem I've sized up thus far, it wasn't nearly as simple as I was expecting, and I definitely hit a few snags along the way.

Forewarning: this is another post for my fellow nerds. For anyone else, it's a valid substitute for a tranquilizer.

The Nitty Grity Technical Details

Depending on how closely you've been following my various love affairs with trendy web technologies, you may or may not know that my site runs on Google's App Engine platform. Knowing very little about how email works, it logically seemed like the App Engine Mail API documentation could maybe potentially be a good place to start. The more I read though, the more foreign concepts I wandered across. What is DKIM? How does SPF work? Do I need an alias? Whose SMTP server am I using? I started to wonder, how bad do I really want email subscriptions anyway? But I, with ample hesitation, plodded down the path anyway.


The ideas behind DKIM are pretty similar to the ones that power TLS and consequently all the important things that happen on the Internet. My understanding of DKIM is that, like, you have a DNS record saying "Yo, this is my public key, use it if you want to see if an email from me is legit" and anyone can see that when they look up records for your domain name ( in my case). Then, every time I send a message [at] frominsidethebox [dot] com, AppEngine adds a special magic signature in the header that's signed with the corresponding private key, and the recipient can use the public key to verify that the signature makes sense and thus the email must have really been sent by me. Cool stuff.


Turns out it's not just for sunscreen anymore. SPF works kind of like DKIM, minus all of the fancy encryption stuff. SPF works by adding another DNS record, but this one says "Bro, if you get a message from my buddy App Engine, you can trust it, he's chill." This way, you can send mail from someone else's mail server and still show that it can be trusted.

At this point, you may be wondering a few things, like Why are all of these things necessary? and Why is Brandon personifying computing protocols and making them sound like frat bros? To answer the former question (and ignore the latter), it's because the Internet is a giant pile of dusty, wobbling, unstable, duct-taped together systems stacked on top of each other like some shoddy version of digital Jenga. The underlying protocol for sending emails reared its head in 1982, and offered literally no way to authenticate where the messages are coming from. It makes sense, it evolved at a time when the "Internet" consisted entirely of academics and the military, so you could just trust the network. It wasn't like some drunk researcher was going to send prank emails, like:

From: Ronald Reagan <>
To: Alexander Haig <>
Subject: fire the nukes
Date: April 1, 1985

Ay Hags,

Launch one of those suckers at the moon, I wanna make it rain nacho cheese.

Ya boy El Prezzo yeah. That'd definitely be a problem today, thus DKIM and SPF.


There was one other acronym I had forgotten to take into consideration: CAN SPAM. CAN SPAM is a US law signed in 2003. It's also the reason all of the (legitimate) emails you get have an "Unsubscribe" link. Not wanting to be at the mercy of the US Government (well, any more than my taxes already cause me to be), I figured it prudent to add one of these "Unsubscribe" links myself. That takes work and effort though, now we're not just blindly (and indefinitely) sending out emails to anyone who sends me an address. Instead, now we have to maintain an active database, and remove people when they ask.

I'm making this sound harder and more complicated than it actually was. All I had to do was add a few web endpoints, and add a new type to my Datastore. The end code (removing the extra boring parts) looked something like:

// Email actions
http.HandleFunc("/subscribe", confirmationHandler)
http.HandleFunc("/confirm", subscribeHandler)
http.HandleFunc("/unsubscribe", unsubscribeHandler)

// When someone submits their email
func confirmationHandler(w http.ResponseWriter, r *http.Request) {
  address := strings.TrimSpace(r.PostFormValue("email"))

  // Do a few basic validations

  exists, err := db.EMailExists(address)
  if err != nil || exists{
    // Return an error

  id, err := db.CreateEMail(address)
  if err != nil {
    // Return a different error

  data := struct {
    ID int64
  var buf bytes.Buffer
  if err := emailTemplate.ExecuteTemplate(&buf, "confirm.html", data); err != nil {
    // Yet another error
// Send email with data in buffer, that basically says "Click here to subscribe"

// Someone clicking the confirm link I sent them
func subscribeHandler(w http.ResponseWriter, r *http.Request) {
  id, err := strconv.ParseInt(r.FormValue("key"), 10, 64)
  if err != nil {
    // Uh oh, looks like nobody is subscribing today

  if err := db.ConfirmEMail(id); err != nil {
    // Experiencing some technical difficulties

  render(w, BasicTemplate{
    Description: "Your subscription has been added.",
    Header:      "You're all set!",
    Message:     "Good to go.",
    Type:        "success",

// Someone doesn't want my ramblings in their inbox anymore
func unsubscribeHandler(w http.ResponseWriter, r *http.Request) {
  id, err := strconv.ParseInt(r.FormValue("key"), 10, 64)
  if err != nil {
    // Uh oh, they aren't going to like this

  if err := db.DeleteEMail(id); err != nil {
    // Looks like they're stuck with me until I learn how to program better

 render(w, BasicTemplate{
    Description: "Your subscription has been removed.",
    Header:      "You're all set!",
    Message:     "Good to go.",
    Type:        "success",

// The struct used to hold subscriptions
type Subscription struct {
  Address   string
  Confirmed bool
  Added     time.Time
  ID        int64 `datastore:"-"`

Woah Brandon, when did you add highlighted code snippets to the site?!

I'm glad you noticed, hypothetical reader! I added it a few months ago, but this is the first post to actually utilize it. It uses highlight.js behind the scenes, and took like five lines of code to set up. But I'm getting sidetracked here. As for the code above, that's really all I needed to satisfy the CAN SPAM act requirements, all in all not too bad. Granted, that doesn't include the code for actually sending emails, but we're getting there.

Actually Sending Mail

Okay, so at this point in the narrative, we've set up DKIM and SPF to work with App Engine, and we've got a storage system set up for subscriptions. According to the documentation, all we need to do now is add:

subs, err := db.Subscriptions(ctx)
if err != nil {
  // Looks like no emails are going out today

for _, sub := range subs {
  data := struct {
    ID int64
  var buf bytes.Buffer
  if err := emailTemplate.ExecuteTemplate(&buf, "new_post.html", data); err != nil {
    // Guess we're not sending this one
  mail.Send(ctx, &mail.Message{
    Sender: "",
    To: sub.Address,
    Subject: "New Post on From Inside The Box: " + post.Title,
    Body: buf.String(),

Hook that up to some authenticated web endpoint, pass in the post ID as a parameter, and boom, you've got a working subscription system. Shockingly enough, that's pretty much all it took to get working. Not only did it work, it worked on (nearly) the first try, no less. In fact, it was so easy that I was sure something would break in the not-too-distant future, as my experience with trucks and things and life in general has shown me to be universally true.

Mistake #1: Not Reading the Manual

A bit of background: I have a special button I push when I want to send out emails to subscribers. It's separate from the special button for publishing posts, because in the event that I accidentally publish something too early, I'd rather not spam everyone with my half-baked ramblings. And if anything goes wrong in the email-sending process after I push my special button, the server will return a message. For a month or two, this process worked well. Things were going along swimmingly, and then one time I pushed the special email button, and things stopped swimming. I got an error that of my 106 subscription emails, 6 of them didn't send.

Huh, that's a bit suspicious, exactly 100 emails sent successfully...

After the slightest bit of sleuthing, I found out that App Engine has some limits and quotas, a particualrly relevant one being that I can't send more than 100 emails a day. This works fine when ≤100 people are subscribed, but not so well when 106 people are subscribed. Sorry to the 6 people who didn't receive an email when I put up this post, unfortunately my logging was also bad enough that I didn't know which six subscribers didn't get a letter, so the best thing I could do was fix the problem for the future. Enter stage right, SendGrid.

SendGrid is a mail-delivery service. They do lots of other things too, but those aren't quite as relevant or interesting to me. All I care about was that they'd happily send way more than 100 emails. So I ripped out the App Engine mailing code, and pulled in SendGrid's Go client library. It took about an hour to throw together, and the only real difference is that I have to pass the SendGrid API key, which I embed directly in my code because I have no sense for design or regard for security.*

Mistake #2: Just Generally Being Incompetent

If you look at the mail snippet above, you might notice one teensy little problem, mainly that I'm just iterating over all the subscriptions and making a blocking call to send a message. This is fine when you only have a few users, but it scales linearly with the number of subscriptions. Not only that, but most of the time spent sending each message is waiting for the request to trot off to The Internet At Large™ and mosey on back. This is a shame, because Go has all these fancy concurrency primitives that I'm not taking advantage of, and would be particularly well-suited to this embarrassingly parallel problem. Using goroutines, we can fire off all the requests, which will then do all that waiting in the background. Similar to my last performance post, it means we can send all of the emails in (almost, kinda sort if you squint a little bit) constant time, instead of watching it get slower as I get more subscribers.

Sounds great right? Well it would be if I was a less shoddy programmer. Concurrency can be tricky to get right (even in a language built for it) if you aren't being careful, and I wasn't thinking. Here's the problem: each email is slightly different because the unsubscribe link has a unique ID for each subscriber, so I can't fire off the same email for everyone. See if you can spot where I went wrong in this first implementation:

var buf bytes.Buffer
data := struct {
  Unsub  int64
  PostID int64
  Desc   string

var wg sync.WaitGroup
// Iterate over list of subscribers
for _, email := range emails {
  go func(email *EMail) {
    defer wg.Done()
    data.Unsub = email.ID
    if err := emailTemplate.ExecuteTemplate(&buf, "new_post.html", data); err != nil {
      // Always check your errors kids

    message := sendgrid.NewMail()
    // Build the rest of the message here

    if err := sg.Send(message); err != nil {
      // Log the errors and whatnot

// Wait for all the emails to be sent

...did you see the gorilla mistake? I thought I was being clever by using one buffer for the emails to save memory, but I was really setting myself up for an awful and awfully obvious race condition by writing to the same buffer from 100 different goroutines with no synchronization whatsoever. The end result could have been a number of problems of varying unpleasantness, but what happened, in reality, was that every person got an email containing the emails for EVERYONE concatenated together. Aside from just looking silly, it means that anyone who got one of those emails could have (and still can) click each and every one of the unsubscribe links in the email and unsubscribe >100 people from my mailing list. I greatly appreciate everyone continuing to not do that, but I regularly back up the mailing list just in case.

The first thing I did to fix this was to give each goroutine its own buffer. Then, I wrote some beefy unit and integration tests for the mailing system. Once I was satisfied with the passing tests, I ripped out all the mailing code, and replaced it with a pool of mailer threads that get fed subscriber IDs via a channel. That way, I only need as many buffers as workers in the pool. The first few attempts caused the tests to fail for one reason or another (malformed message bodies, deadlocks, etc), but I eventually got it working. I'm going to skip including that code, because this post is already probably too long, but you get the idea.

Last Thing: TLS

All this talk of email is great, but there was one oversight on my part that I'd been avoiding because it was convenient to do so. My site was being served over HTTP, not HTTPS, so if you clicked the "Subscribe" button, it'd be sending your email address over the open Internet. Not a huge deal, but it's 2016 and I can do better than that. So with that in mind (and a bit of prodding from a friend), I started looking up the process for getting TLS on a custom domain with App Engine. I also wasn't ecstatic about the idea of paying a signing authority for a certificate, so I looked into Let's Encrypt. I ended up finding a few great guides on how to set it all up, then I just had to switch my image serving over to HTTPS, and add a "secure: true" in my App Engine app.yaml configuration so that it would always redirect to the HTTPS version of the site and that was it! I don't know about you, but the green lock in the address bar gives me a warm, fuzzy feeling.

*I'm joking, of course. What kind of idiot would mix credentials with code? Kidding again, I'm that kind of idiot and that's exactly what I do, but I swear I have every intention of having a separate Datastore table to store all of the private keys I need for the application. In the mean time, my source code is stored in a private Github repository, only accessible via two-factor or private key authentication. Granted, I'm still putting quite a bit of faith in Github here, but the stakes aren't all that high for this particular case.


If you want to get emailed when I write a post, add your email here. Don't worry, you can always unsubscribe.