Why You Should Open Source Your Thinking

Open source software (OSS) has transformed the technology landscape. I can't imagine any software company build without OSS at the core.

What makes OSS magical is the serendipity of how it's created. Someone throws an initial idea on the internet, and if others have the same problem, they join in and organically refine and improve the original idea. Others silently lurk into the project, start using it, and run into some bugs or edge cases which they report (and sometimes post a fix for). Before you know it, there's a robust piece of software that has been tested under a variety of circumstances by experts around the world.


Blogging has similar properties. Someone can post an idea, which is then improved upon or augmented by the community. Unlike software, the mechanics (i.e. GitHub) don't easily exist to collaboratively discuss a particular part of the idea or concept that is being written (what a cool product that would be! Holloway is doing something similar).

I think posts written as a breakdown of someone's thinking on a particular topic, without any hidden agenda, have the best chance of creating the OSS dynamic. For instance, by reading Stephen Wolfram's explanation of his productivity system, you'll probably end up tweaking your own working style or adopting some of his tricks. Reading how someone else learned a programming language may change how you approach learning. A packing list for a family with four kids may help augment your own travel strategy and inspire you to travel the world with your kids. Reading how someone manages their finances, consumes information, purchases insurance, will help you revise and improve your own processes.

I think of these posts as "open sourcing your thinking". Documenting how you approach a specific topic with enough detail and vulnerability helps you clarify your own ideas but more importantly allows your ideas to be critiqued and improved by the larger internet community (just like OSS).

I'm going to be doing more of this. And, selfishly, I hope you do the same so I can learn from you!

Continue Reading

Optimize Your Charitable Giving Using a Donor Advised Fund (DAF)

I've always been fascinated with the idea of recurring revenue. Building a business or a portfolio of investments which passively create recurring income has been interesting to me since I got my first paycheck.

Over the last year I've been thinking: why can't I (slowly) create a charitable asset that kicks off income each year which can go tax-free to charities? This way, instead of giving to an organization once, you can build a mix of assets that generate enough income to perpetually give to the organizations you carry about?

This idea, combined with the recent tax law changes that made it more challenging to get a deduction from charitable donations (10k SALT limitation makes it harder to itemize), got me researching. I ended up finding an interesting vechicle which I hadn't heard of before: the Donor Advised Fund (DAF).

Obviously, I'm not a financial advisor, lawyer, CPA, etc. Don't trust anything you read here, and always consult your own advisors. 

How a Donor Advised Fund Works

Here's the basics of how a DAF works:

You 'join' a DAF run by an independent organization. There's a minimum (~$5k) to opening up an account with DAFs (Fidelity, Vanguard, etc). These organizations charge a management fee (~0.5% of assets). You donate to the tax-deductible DAF. When you donate to the DAF, you are giving away any legal control over that money. The DAF can technically do whatever they'd like with it. However, you can 'advise' the fund where you'd like them to donate. Essentially, this means you control exactly where the money in the fund flows. You don't have to donate everything that you put into the fund within the same calendar year

Here's why it's powerful:

You only have one tax slip at the end of the year from the DAF. No more chasing down charities to properly document your charitable giving! You can 'batch' donations in a single year to the DAF get above the standard dedution, but distribute money to charities across a number of years. While the money is in the DAF and not distributed to a charity you can invest the cash in low-cost index funds. You could structure the DAF so you only distribute earnings from your invested cash. If you have a cash windfall, you can make a large donation in the same tax year to the DAF to get the deduction, but decide later exactly what charity you'd like to distribute the funds. It's easier to control the organizations you donate to: instead of organizations charging your card every month, you can setup monthly/quarterly/yearly donations which are sent to various organizations. You don't have to worry about organizations not canceling your recurring donation or contacting them to change your donation. You can manage all your donations from a central dashboard.

I've been using the Fidelity Charitable DAF for the last year and it's been awesome. The management fees and minimums made the most sense for my situation, plus it seemed like they had the best website. The Vanguard and Schwab options seemed about the same.

Some interesting threads/links I found along the way:

Reddit Analysis of DAFs Boglehead Thread Alliance for Good What's the Catch?

From what I can tell, there isn't any.

For some reason, the DAF hasn't been advertised heavily. Probably because the number of folks willing to donate about the minimums (~5k for the initial setup) isn't huge, and non-profits have an incentive to maintain a direct relationship with the donor and ping their card every month (with a DAF you control the fund outflow).

However, there are some limitations/downsides to be aware of:

You are legally removing control over the money. Theoritically, the organization managing the DAF could do whatever they'd like with it. There are some limitations to organizations beyond 501(c)(3) you can donate to. A ~0.5% management fee is charged on a yearly basis. What About Foundations? Or a 501(c)(3)?

I've heard differing opinions on if it makes sense to open up your own foundation.

Some folks have said that the legal and compliance overhead with foundations are not worth it unless you have 100s of thousands to give away. 5-10 This seems to align with what I've seen (through my wife who worked in non-profit development)—only very large donors seem to maintain a foundation in their name, and foundations seem to have a bunch more rules to follow and compliance to worry about.

I've also heard about some folks who open their own 501(c)(3) and park their charitable donations there. From my cursory research, non-profit organizations have the same or more overhead compared to a foundation.

In my analysis, the simplicity and relatively low management fees of the DAF make it the best choice for most folks.

A foundation or 501(c)(3) would make sense for very high net-worth individuals, or the unique person who has the time/savvy/interest to read through & file the paperwork and ensure there aren't any compliance issues. I'm more keen to keep things simple and eliminate overhead, even if it means reduced control or slightly higher costs. KISS, baby.

Why Everyone Should Give

You might ask why this matters, or why you should give at all. Here's my perspective.

I believe strongly that everyone, regardless of their income level, should give something to the community they are a part of. This doesn't always mean money, but it does mean something valuable (time, things, ideas, etc) that helps others around you.

It's easy to become very self-centered and giving counteracts the natural force that makes life all about us. For most of us, many other people have been given a set of circumstances that make life much harder than our own. Giving (especially when it's significant enough to 'hurt') makes us aware of those around us less fortunate and ensures we live a life for others, and not ourselves.

Continue Reading

Habits, Systems, and Scripts

I've been 'auditing' various areas of my life.

After being obsessively focused on work for a long time, it's been helpful to think deeply about the habits and pre-written scripts that I've developed across a bunch of areas of life. In most cases, the habits I've adopted over the years are a function of taking the path of least resistance than an intentional choice.

Here are some things I'm looking at:

Information Consumption (news, email, podcasts, reading, etc) Exercise Eating Prayer Marriage Friendship

Thinking through what I want from these categories, where I'm not satisfied, and asking 'why' multiple times until I get the root cause of the delta has been insightful. It's allowed me to rewrite the default scripts I operate out of and make meaningful change very quickly.

It takes intentional effort & dedicated time to create clarity in your thinking to focus in on what needs to change and to generate the excitement to do it.

Take some time and audit areas of your life that you've ignored because of laziness or busyness. It's worth it.

Continue Reading

Handling Web Timeouts in Heroku

I'm a huge fan of Heroku. Way back when, I used to manage the entire deployment infrastructure manually. I'd grab a VPS from RackSpace/AWS, install nginx, configure ruby, tinker with deployment scripts, and then in the weeks ahead endlessly tinker with settings when things didn't work just right. Although I did enjoy the capture-the-flag feel of finding the right service configuration to solve a problem, once Heroku became a thing I switched over every application I managed.

There's a huge amount of leverage in never having to worry about the details of your deployment infrastructure. Heroku is expensive, but it's orders-of-magnitude cheaper than hiring a devops expert.

However, there are some limitations. The one you'll most likely run into is the 30-second web worker timeout. If your web request doesn't finish in time, it will be killed and the user receives a 500 error. Not good.

A much better UX is displaying some sort of 'loading slowly, please refresh' message to the user and implementing progressive caching. This way, if there is some sort of slow service causing an IO block, you can cache the response in the first request made by the user, so the second page load attempt works successfully.

(You may be wondering why a page load would ever take 30s. Great question. I work a lot with NetSuite, and sometimes need to pull content dynamically. If there is an API slowdown—which happens often—this can cause the page load time to spike).

The best way I've found to gracefully handle this situation is to use the ruby stdlib Timeout::timeoutmethod to throw an exception after 29 seconds. However, this method is dangerous. You'll want to first understand how this operates under the hood:


In your rails controller, here's how you can 'protect' a method that could run for a long time and display a friendly timeout page instead of a standard 500.

class ApplicationController rescue_from WebWorkerTimeoutError do render :timeout end around_action :raise_on_web_timeout, only: :show def show @state = the_long_running_thing end def raise_on_web_timeout Timeout::timeout(29, WebWorkerTimeoutError) do yield end end end

Continue Reading

The Feeling of Fast

Momentum is a powerful force. Once you are moving it's easier to get keep moving. If you've already crossed off an item or two on a less-than-ten-item todo list, you'll be able to get the rest of the tasks done faster.

The perception of speed is sometimes more important than your absolute speed. I've found that the "feeling of fast" creates the momentum that drives effective execution.

It's worth spending the time and money to optimize various aspects of your work & life in order to create a feeling of moving quickly.

For example:

A faster computer or phone reduces friction and makes it feel like you are getting more done. Using more keyboard shortcuts, or writing tools to automate repetitive tasks, can increase your velocity. Getting a treadmill desk can literally create the feeling that you are moving quickly. Using a VA to offload tasks which are time-consuming, boring, and uninteresting can make it seem like you got them off your plate quickly. If you have a tendency, as I do, to analyze small decisions too much making a decision within a pre-determined time-box can keep you moving quickly. If you are constantly refilling your Brita water filter, buy an under-the-sink filter with a reservoir so you'll never need to wait for water to filter.

Think about what is annoying, what makes you feel slow, and improve it. It's worth the up-front investment.

Continue Reading

2018 Goal Retrospective

Every year I enjoy doing a retrospective on last year's goals. I believe there is value is "open sourcing your brain": your ideas may help someone and you may get invaluable feedback to help you improve.  There's also a strange sense of social accountability created for myself that helps me ensure I improve this year.

So, with that in mind, here we go!

What worked Doing something small to move a goal forward. Once you see progress you'll be motivated to dig into the goal more and make progress. Reduce friction on goals which you are not naturally motivated to achieve. For instance, if you want to drink more water everyday, buy a water purifier to make the water taste better. Scheduling time on Sunday to work on goals. Other days of the week are very busy and my mind is generally "spent" by the end of the week.

Some additional context on #1 & #2:

One of my goals this year was improving my health: losing weight, eating better, etc. This is something I've never been good at or motivated to improve.

I've found that if I'm not making progress on a goal, especially when I'm not naturally motivated to hit it, it's because there is not a clear path to making progress. For instance, my health goal was to hit a specific weight and BMI. I don't know how to work out: my family, friends, and school never taught me and I never invested in it. I have such little knowledge of the space I don't really know where to get started.

What was really effective for me was setting up a little space in my house where I could do pushups and planks. I'm not sure if those exercises were the "best" to do, but I know how to do them well enough. I can do them at home, they don't take much time, and it's easy to see progress. I walk past the area I setup and it requires so little mental energy to take 10m and do the exercises that I've ended up doing them more consistently.

The lesson here for me is to break down large goals into a small actionable task and reduce the friction involved in accomplishing the task.

What didn't Quarterly review. We (my wife and I) did a great job on our weekly and monthly reviews, but just didn't do the quarterly reviews. We also didn't acknowledge this and adjust through the year. Health goals. I don't enjoy working out. It has always been a chore that required a bunch of my daily "decision making quota" to push myself to do it. I started making progress at the end of the year, but overall I barely made progress. Not scheduling enough time on Sunday to work on goals. There was one goal this year which I didn't hit just because I didn't schedule a couple more hours to create a plan and strategy that I could easily execute on throughout the week. Not bringing in help/accountability on a goal that is slipping. I'm wired to figure things out on my own, but sometimes (ex: exercise) it's best to bring in a professional to help provide external motivation and personalized information to put me on a clear track to accomplishing my goal. Developing new habits. I only have so much decision making power, or discipline, each day. Each time I need to make a decision I withdraw from my "decision bank account". This is why automating or eliminating as many decisions as possible is very powerful. It's also why I can't seem to develop more than one or two habits at a time. This last year I was not intentional about which habits I was working on and didn't ensure I had enough "discipline budget" to effectively build the habit. Running a business by yourself can take over your life. It's very hard to do anything but work on important and urgent items for the business. I created a "2018 Goal Dashboard" and didn't look at it at all. Keeping yet one additional thing up to date wasn't effective and it wasn't inspiring keeping a digital sheet full of gauges up to date. The meta-lesson here is being aware of adding more weight to a process. Be thoughtful about what the minimum overhead is required to accomplish your goals. What am I going to change? We didn't stick to our quarterly reviews. I think we need to shorten the review to make it quick: ~30m. The length of time that it takes to effectively do the review is what caused it to be harder to execute on. Don't attempt to make big life or habit changes when you are starting a business. Be honest with yourself and realize that creating a successful business is going to take every ounce of effort you have and every other major category of your life will be on autopilot. The type of business does matter here: if you are creating a coaching business, a small info-product business, etc that you aren't relying on to provide for your family this is a different story. Every 2-3 months we need to schedule a 3-4 hour block of time on Sunday to work on our goals. This dedicated time on a day when there's no other urgent obligations is critical to creating a strategy for moving forward on the more challenging goals. There's got to be an easy physical way to update the large goals for the year. Maybe some sort of board with the goals written down that you visit throughout the year.

I'll report back in 2020 with how this year's goals went.

Continue Reading

How to Create a Custom Field to a NetSuite Customer or Transaction

NetSuite custom fields are incredibly powerful and flexible, but they are not easy to work with! Below is a quick guide that walks through how to create customer and transaction custom fields and some tips and tricks for working with custom fields.

How to create a custom customer (i.e. entity) field in NetSuite: Navigate to: Customization > Lists, Records & Fields > Entity Fields > New Label: use a name you'd like to see displayed on your customer. Type: "Free-form Text". There are cases where you won't want to use free-form text, but in most cases this is the best option. ID: "_a_internal_identifier". Note that you should start your identifier with a _ since custentity will be prepended to whatever you provide here. You'll want to change "_a_internal_identifier" to an ID that is descriptive of this field in your setup. Store value: checked Applies to: Customer Save How to create a transaction (invoice, cash sale, order, payment, etc) field in NetSuite: Navigate to: Customization > Transaction Body Fields > New Label: use a name you'd like to see displayed on your transaction. ID: _a_internal_identifier. Note that you should start your identifier with a _ since custbody will be prepended to whatever you provide here. Type: free form text Store Value: checked Applies to: Sale, Payment, etc. Where you want this field displayed is up to your use-case. Global Search: checked. This enables you to search for the value in the NetSuite global search Save Other Tips & Tricks for Working With NetSuite Custom Fields Customer (entity) custom fields will always start with custentity. Transaction (invoice, sales order, payment, etc) custom fields will always start with custbody. You can create custom fields on most, but not all records. For instance, you can't create a custom field on the currency record in NetSuite but you can create one on a subsidiary. It's possible to access "hidden" fields that are not available through SuiteTalk or SuiteScript using field defaults or formula field defaults on custom fields. You can source values from a related record. For instance, if you want to source a value from a CashSale connected to a CashRefund you could use a formula like {createdfrom.externalid} as the default value for a field that doesn't store a value. A field which does not store value (i.e. a field that just contains a default value) is not available via a formula on another field. A field not found error will be reported. In other words, you can't nest formulas. This is a huge bummer. If "formula" is not checked when creating the custom field you can still substitute field values using the {field} syntax You'll get ERROR: Invalid Expression for lots of different types of errors. For instance, if your formula doesn't output the correct field type you'll get this error. This makes it very challenging to debug why a formula isn't working. Join fields (i.e. {entity.datecreated}) strips the value of its type. Everything comes over as a string. You can use SQL functions in a formula field default

Continue Reading

2017 Goal Retrospective

I love yearly goal planning with my wife. It's been an awesome practice that we started years ago thanks to The Best Year Ever program and the promptings of David DeWolf. It's truly changed our lives: it's amazing to see how many big, important goals you can hit each year if you have focus and clarity at the outset of the year.

I try to do a retrospective in most areas of my life, but I especially enjoy doing one in regards to my yearly goals. I've found identifying and implementing small, incremental improvements to important aspects of life to be incredibly useful.

What worked:

Our weekly review reminded me of key goals and maintained momentum towards hitting them, even when I lost motivation or felt overwhelmed with other demands on my time. This last year was a busy one for us, and we paired down our goals from the outset to account for this. Being realistic about what can be accomplished based on your season of life is important. Although our goals were "boring" this past year, they were the right ones for our season of life. It's ok to have boring goals that are important—but not every year! Over the long-term, they need to be exciting. Two of my goals were habits that I wanted to develop. I think if there were more than two habits, this wouldn't be as effective, but having two habits to focus on each week was very powerful.

What didn't:

We only did our quarterly review once. We use the quarterly review time to edit our goals (and sometimes remove!), change our strategy, or adjust goal metrics if what we originally set out to do was unrealistic. Additionally, not having this time set aside eliminated the possibility for us to have dedicated time to work on key goals that were slipping.

I also find that keeping goals around that need to removed or edited is demotivating. I skip over them and immediately discount them, which affects how I perceive the rest of the goals on my list.

Here's what needs to change:

We need to add more fun to the quarterly review process. For the yearly review, we try to take a trip and get out of our normal life for a couple of days, but for the quarterly reviews we've never done this. Combining the process with a fun experience will help us look forward to the process more and make sure it happens. A Groupon hotel deal is a great (and cheap!) way to make this happen. There's a distinction between key habits and goals. For us, we've always treated habits that we want to develop as goals. However, there are important habits that we've developed (or are still working on!) that we want to make sure we maintain. I'm going to try to develop a list of habits and creatively think of a way to track our commitment to critical habits over time. Not sure how to do this yet without creating more work/time for us.

Continue Reading

Notes on Working with Jobs (Projects) using the SuiteTalk NetSuite API

Jobs are a confusing part of the NetSuite system. Here's some notes and resources to help make handling jobs easier:

Jobs are named Projects in the GUI There are two versions of jobs: "standard" and "Advanced Jobs". They both use the same core job record but change how the data is structured on the customer. Jobs have a kcustomer attribute that is not accessible via SuiteTalk which represents the customer that the job is associated with. This field is accessible via SuiteScript. You could most likely expose this field by creating a formula field on the job record with {kcustomer} as the formula. There is no customer field on the job schema However, there is a customer field on the job search columns. You can use an advanced search to return the customer associated with a job. If "Project Management" is enabled (aka ADVANCEDJOBS) the entity reference on the customer is a customer during the edit view, but will switch to be a job reference when the record is saved. When ADVANCEDJOBS is disabled the job reference could be either a customer or a job and the job field is not displayed. The parent field on a job can reference a customer. I believe you can have an heirarchy of jobs so it can be possible for the parent to be a job reference. Since the kcustomer field is not exposed via SuiteTalk the only way to determine the correct customer reference is to walk up the hierarchy.


Determine the customer associated with a job via SuiteTalk SuiteScript to extract a valid customer reference from an entity ID Determining if an entity ID is a customer or a project

Continue Reading

Notes on Dates & TimeZones with NetSuite’s SuiteTalk API

Setting date and datetime fields in NetSuite using the SuiteTalk API is tricky business. Here's some notes on how to ensure that the date you push over to NetSuite persists the way you'd expect regardless of the server, local server, user, and company timezone.

The API is sensitive to the timezone of the current user. If you push the same datetime value to the XML via SuiteTalk, and change the timezone settings on the user preferences page, the resulting date set on the record will most likely change. The timezone is not available on the employee record. Also, the timezone is not available on the company/subsidiary record. It is impossible to determine the timezone set on the user or the company from the SuiteTalk API. The get_server_time method does not return the time in the current user's timezone preference. There is no SuiteScript-specific method to getting a timezone. Although it looks like you can infer it from the stdlib JS responses. It could be possible to create a RESTlet bundle that could retrieve the timezone of the current user as a JSON response. If the timezone of the user (employee) differs from the timezone of the request NetSuite will convert the datetime in the request to the timezone of the current user. If you push a date of 2017-04-17T00:00:00-07:00 and the user's timezone is GMT -04:00 the resulting date field in NetSuite returns 2017-04-16T21:00:00-07:00. This appears properly as 04/17 in the GUI for the current user as well as for other users with different timezone configurations. If you push a date in the timezone of the NetSuite servers (PDT) NetSuite seems to ignore the timezone of the user used to make the request. Note that accounting for DST offset and zeroing out the hours, minutes, seconds is essential to making this work. Here's an example of what your date should look like 2017-04-17T00:00:00-07:00. If you push a date one second after midnight NetSuite will take into account the user's timezone. Best practice: convert your date to UTC0 and use NetSuite::Utilities.normalize_time_to_netsuite_date(time_stamp). This utility will handle DST, zeroing out hr/minute/seconds, and convert the datetime to the right format for SuiteTalk. The date returned by the API is adjusted based on the user's timezone. For instance, if you push 2017-04-17T00:00:00-07:00 to NetSuite with a user whose timezone is set to EST the date returned by the API will be 2017-04-16T17:00:00-07:00 although it will properly display as 2017-04-17 in the GUI.


NetSuite ruby client conversion utility https://netsuite.custhelp.com/app/answers/detail/a_id/34163/kw/TIMEZONE https://netsuite.custhelp.com/app/answers/detail/a_id/43268/kw/TIMEZONE https://netsuite.custhelp.com/app/answers/detail/a_id/44687/kw/TIMEZONE Converting between time and datetime in ruby Modifying time without railscn

Continue Reading