<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Random Title, Working Thoughts</title>
 <link href="http://santtu.iki.fi/atom.xml" rel="self"/>
 <link href="http://santtu.iki.fi/"/>
 <updated>2023-06-27T18:12:56+00:00</updated>
 <id>http://santtu.iki.fi</id>
 <author>
   <name>Santeri Paavolainen</name>
   <email>santtu@iki.fi</email>
 </author>

 
 <entry>
   <title>AWS & strategy over the years</title>
   <link href="http://santtu.iki.fi/2018/11/30/aws-strategy-changes"/>
   <updated>2018-11-30T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/11/30/aws-strategy-changes</id>
   <content type="html">&lt;p&gt;I started using and consulting on AWS somewhere around 2008. Over the
years AWS has extended its service portfolio and its geographic
presence, not to speak of the huge increase in computing and storage
capacity in all its datacenters.&lt;/p&gt;

&lt;p&gt;While the increase in geographical reach and absolute capacity are
easy to understand — simple response to raw customer demand — the
updates to service portfolio require more thinking. Why this service?
Why at that particular time? Are there any clear patterns? Could you
predict future AWS services?&lt;/p&gt;

&lt;h2 id=&quot;viewpoint-adoption-life-cycle&quot;&gt;Viewpoint: Adoption life cycle&lt;/h2&gt;

&lt;p&gt;One can look at AWS through the &lt;a href=&quot;https://en.wikipedia.org/wiki/Technology_adoption_life_cycle&quot;&gt;adoption life
cycle&lt;/a&gt;,
and say that&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Initially AWS targeted innovators by producing
&lt;strong&gt;useful MVP services&lt;/strong&gt; (I’ve discussed &lt;a href=&quot;/2013/07/10/one-viewpoint-on-cloud#so-wtbf-about-startups&quot;&gt;one aspect of this&lt;/a&gt; in 2013 and still stand by that reasoning.)&lt;/li&gt;
  &lt;li&gt;Once “cloud” became as a viable business platform (“early
adopters”), it broadened its service coverage.&lt;/li&gt;
  &lt;li&gt;… and so on …&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;viewpoint-developer-visible-phases&quot;&gt;Viewpoint: Developer-visible phases&lt;/h2&gt;

&lt;p&gt;I chance at another timeline categorization based on my own perception
of &lt;em&gt;using AWS services&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Establishing “cloud” as a viable option for new development
projects, offering minimal but valuable services via leveragable
interfaces (aka APIs)&lt;/li&gt;
  &lt;li&gt;Pivoting towards making AWS viable for enterprises to integrate and
later migrate existing systems to, adding more varied and less
developer-focused services, expanding features of existing services&lt;/li&gt;
  &lt;li&gt;Making everybody’s head spin with a plethora of overlapping and
confusing services announced at increasingly rapid pace&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two are clear, and I would put the dividing line between
those two phases at the the &lt;strong&gt;introduction of VPC in August 2011 and
Direct Connect in September 2011&lt;/strong&gt;. Why? Because Direct Connect makes
more sense in integration with existing workloads in enterprise data
center than for cloud-only projects. While VPCs were useful for
cloud-native workloads, they were essential for enterprise data center
integration and Direct Connect.&lt;/p&gt;

&lt;p&gt;This does not mean that enterprises jumped on AWS bandwagon at that
point. No no no! — Yet, there is a strategy. Simple toe-dipping
projects can be isolated, but to do real business, enterprises needed
integration with existing CRM and ERP systems. For that, more
enterprise-oriented features came along. Eventually enterprises gained
more confidence and actually started migrating &lt;strong&gt;existing&lt;/strong&gt; workloads
off their own data centers (an obvious progression).&lt;/p&gt;

&lt;h2 id=&quot;viewpoint-software-engineers-aka-chaotic-code-cranking-machines&quot;&gt;Viewpoint: Software engineers a.k.a. chaotic code cranking machines&lt;/h2&gt;

&lt;p&gt;What about the third step, the head spinning and confusion? (I alluded
this &lt;a href=&quot;2015-01-03-year-of-the-cloud&quot;&gt;in 2015&lt;/a&gt; when lamenting the loss
of “expert cloud generalist”.)&lt;/p&gt;

&lt;p&gt;AWS is announcing new services and new features on existing services
at an astonishing pace. Some years back I looked at AWS’s open
positions, and was thinking &lt;em&gt;like why is AWS hiring all these
developers?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To write software&lt;/em&gt;, of course. For existing services? No, while you
need &lt;em&gt;some&lt;/em&gt; more people when the service is growing exponentially, the
basic tenet of cloud engineering it to create systems that &lt;em&gt;scale
well&lt;/em&gt;. Neither it was tenable that AWS’s retention would have been so
bad to require hiring software engineers at the pace that was apparent
from their open positions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To write software for &lt;strong&gt;new services&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It often feels that AWS is overrun by engineering teams and service
ideas and cannot always produce coherent and co-working
interfaces. Maybe we are a phase where AWS usage is growing so fast,
they put resources to any development that seems to be “cloud”.&lt;/p&gt;

&lt;p&gt;This is a possibility, but it might not be true, or only a partial
truth.&lt;/p&gt;

&lt;h2 id=&quot;viewpoint-its-all-intentional&quot;&gt;Viewpoint: It’s all intentional&lt;/h2&gt;

&lt;p&gt;Another, a bit more sinister possibility is that AWS is doing the
&lt;strong&gt;innovate-leverage-commoditize&lt;/strong&gt; (ILC) cycle faster, and faster, and
with more and more software engineers (speeding up internal
development cycle multiplied by more developers)&lt;/p&gt;

&lt;p&gt;You really should check &lt;a href=&quot;https://blog.gardeviance.org/&quot;&gt;Simon
Wardley’s&lt;/a&gt; work on strategy. I’ll let
this one tweet from him (with pictures!) lead into why he things AWS
is getting faster.&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;
  &lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;X: Why do you think Amazon is so dangerous? Don't you think they will slow down?&lt;br /&gt;Me: No, they'll get faster.&lt;a href=&quot;https://t.co/LiUlzyn9RZ&quot;&gt;https://t.co/LiUlzyn9RZ&lt;/a&gt; &lt;a href=&quot;https://t.co/TpWmGdulaQ&quot;&gt;pic.twitter.com/TpWmGdulaQ&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;— Simon Wardley #EEA (@swardley) &lt;a href=&quot;https://twitter.com/swardley/status/924794617211572224?ref_src=twsrc%5Etfw&quot;&gt;30. lokakuuta 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just looking at the &lt;a href=&quot;https://web.archive.org/web/20181129181700/https://aws.amazon.com/new/reinvent/&quot;&gt;ludicrous number of launches and
updates&lt;/a&gt;
would appear to support better the former — chaos —
hypothesis. WTF satellite ground station as a
&lt;a href=&quot;https://aws.amazon.com/blogs/aws/aws-ground-station-ingest-and-process-data-from-orbiting-satellites/&quot;&gt;service&lt;/a&gt;?
That’s hardly a high-volume low-margin business. What is next,
purchase satellites on a credit card?&lt;/p&gt;

&lt;p&gt;On the other hand, it could be that Amazon is using AWS’s momentum in
the cloud space to rush into any high-margin high technology area, and
assume it has the technological cloud and enough runway to cause chaos
and panic on incumbents in any area (satellites?). Leapfrogging to
providing lower cost, automated, self-service,
&lt;em&gt;something&lt;/em&gt;-as-a-service, attempting to exploit the inherent slowness
and obstacles of existing market players.&lt;/p&gt;

&lt;p&gt;In this context, it would not be a terrible loss if some of these
eventually fail. Why would you attempt to compete in the current
market, when you have the chance of owning the future market?&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;I am no strategist, but I’ve learned that most of what &lt;em&gt;appears&lt;/em&gt; as
strategy is often just a retroactive narrative. What in reality was a
&lt;em&gt;jumble of intentional strategies, bunch of accidents and a lot of
groping in the dark&lt;/em&gt; is often cleaned up, diced and re-assembled into
a narrative that promotes the supreme wisdom of the &lt;strike&gt;supreme
leader&lt;/strike&gt; company. The question is not whether Amazon slash AWS
is chaotic. It undoubtedly is, and a lot of the history will be
written into a nice, retroactive, primetime story. Nevertheless, this
does not exclude the possibility that amid all of the chaos there is a
conscious, strategic direction being implemented.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;(You can see all posts from re:Invent 2018 footpedalling down the
&lt;a href=&quot;/tags.html#reinvent2018-ref&quot;&gt;reinvent2018&lt;/a&gt; tag.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Betatesting AWS certifications tests</title>
   <link href="http://santtu.iki.fi/2018/11/28/aws-certs"/>
   <updated>2018-11-28T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/11/28/aws-certs</id>
   <content type="html">&lt;p&gt;I got the whole bunch of AWS certifications in 2012 and 2013 at
re:Invent (bunch = &lt;em&gt;all&lt;/em&gt; that were available). AWS has a tendency to
offer so-called “beta” certification tests at re:Invent. These beta
tests are essentially the “next” set of tests to be rolled out on that
particular certification.&lt;/p&gt;

&lt;p&gt;I do find the idea of using beta testing for tuning of the
certification fascinating. Beta-testing a test … enticing. There are
some major differences between AWS re:Invent beta-certifications and
regular certifications (which are also available):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;They are cheaper: this time at 1/2 price of a regular test.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;They are way longer. There are 220 minutes reserved for beta tests
(170 minutes for non-beta), and I have found that the extra time is
needed. I think there are more questions, but it might also because
the test questions and multichoice answers are not necessarily
always as polished and require more mental effort to work through.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It takes several months to get the test results. For regular test
results you get a pass / no pass result right after the test. I
guess they’ll need to collate and analyze the results and figure out
how to set the scoring etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Some of the problems are … unclear or ambiguous. I’m not talking
about the typical case of finely nuanced question where you’ve got
to be sharp to spot the significance of a single plural. I mean the
kind of questions where there are, for example, two valid answers,
and the differentiating factor just is not mentioned in the
question, no matter how hard one looks for it. Yet, you might have
missed the hint, but … perhaps I am assuming too much of myself.&lt;/p&gt;

    &lt;p&gt;I would still expect these to be — not necessarily made
immediately obvious — but at least changed to make the ambiguity
only superficial and resolvable in the and.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There may be other problems in the questions. Like, having a large
picture in the question, pushing answers behind the fold, with
answers being so long that you need to scroll up and down and up and
down to cross-correlate the answer to the question (or re-draw the
network diagram on a paper).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although, on the face of it, having 50% discount on a test that costs
less than the billable time you put into it … so there might be no
good reason to put in the extra effort and delay associated with beta
exams.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I do AWS certifications solely for business reasons&lt;sup id=&quot;fnref:why&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:why&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;: I don’t
personally put much value in certificates — sorry in advance for
those who got boatloads of them, you might want to stop reading here
— yet I recognize their usefulness in business, in AWS ensuring
their partners retain some people with certain minimum knowledge, in
partners being able to show some proxy of potential capability etc.&lt;/p&gt;

&lt;p&gt;If you think that passing a certification test — say, AWS Solutions
Architect — shows you to be an expert in the field, you are falling
for a &lt;a href=&quot;https://en.wikipedia.org/wiki/Affirming_the_consequent&quot;&gt;logical
fallacy&lt;/a&gt;. Yes,
experts pass the test. But, passing a test does not imply being an
expert.&lt;/p&gt;

&lt;p&gt;You should think a certificate as an … say, sports license. It shows
a certain determination, and at least a belief in your own
potential. It is a ticket to enter a tough competition. It does not
imply that you would prevail.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Anyway, how do I think the tests have changed over time?&lt;/p&gt;

&lt;p&gt;At least for Solutions Architect tests, I’d argue the same way AWS in
general: much more into enterprise side, integration, migration,
security policy concerns, enforcement and auditability.&lt;/p&gt;

&lt;p&gt;At bit more broad than before, which is nice.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;(You can see all posts from re:Invent 2018 pecking the
&lt;a href=&quot;/tags.html#reinvent2018-ref&quot;&gt;reinvent2018&lt;/a&gt; tag.)&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:why&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Primarily for gauging the test difficulty so I can evaluate others whether they are ready to take the test. It is useless — even demoralizing — to put someone on even a practice test if they’re guaranteed a failure. It is better to let them gain experience on the job, through training, or other means so they have a good chance of passing on the first try. This is also one of the reasons I prefer beta exams: it allows you to understand well in advance where the &lt;em&gt;normal&lt;/em&gt; tests are moving towards. &lt;a href=&quot;#fnref:why&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>re:Invent — growth pains</title>
   <link href="http://santtu.iki.fi/2018/11/27/reinvent-practicalities"/>
   <updated>2018-11-27T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/11/27/reinvent-practicalities</id>
   <content type="html">&lt;p&gt;This is a just quick post from re:Invent 2018 conference. I am
planning to later write more on how the cloud industry has changed
over the years since my previous visits at the conference.&lt;/p&gt;

&lt;p&gt;However, for now I am just going to &lt;strike&gt;bitch&lt;/strike&gt;comment on
some practical issues here at re:Invent 2018 and how they relate how
the conference when I visited it the last time in 2012 and 2013.&lt;/p&gt;

&lt;p&gt;(This is being finalized on Tuesday, end of &lt;em&gt;the second day&lt;/em&gt; of the
conference. There are still three days to go.)&lt;/p&gt;

&lt;h2 id=&quot;locations-&quot;&gt;Locations 👎&lt;/h2&gt;

&lt;p&gt;The move from a single location (Sands Expo) to multiple hotels and
conference venues on the strip is problematic:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;You need to transfer between sites unless you can schedule all of
your sessions in a single location (for a day) — the transport
time varies hugely, I’ve gotten from Mirage to Aria in 10 minutes
(morning, light traffic) versus 10 minutes wait time plus 50 minutes
transport time (Aria to Venetian) with queues, full buses, and
an accident clogging the rush-hour congested route.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Given that popular sessions will be full, &lt;strong&gt;not being at the
entrance&lt;/strong&gt; 10 minutes prior to the session can mean complete miss of
that session — definitely frustrating if you missed because of
transport delays. If you had a reserved seat, they expire at 10
minutes prior to the session start, so that’s sort of a double loss
— you made the effort to reserve a seat, then lost the whole
session.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The logistics of planning which sessions and where to attend is just
… the conference app and web site do not help, either. (I wrote &lt;a href=&quot;https://github.com/santtu/reinvent2ics&quot;&gt;a
screen scraper&lt;/a&gt; solely to
generate an ICS file from the planner’s “interests” just to be able
to import them to Google Calendar for easier schedule
management. The fact that the planner app needs wifi to show your
schedule is a back-ass-ward design. Ever heard of offline use? Like,
using AWS’s own mobile services and toolkits?)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nevertheless, I found that &lt;em&gt;not having a registered seat&lt;/em&gt; is not a
huge problem — you’d need to be there 10 minutes in advance
regardless of whether you have a reservation or not. I’ve managed to
get into all sessions so far (I’m sure this streak won’t last, though)
where I’ve been at the door 15 minutes prior as a walk-up (no seat
registration) attendee. (Which reminds me, that as of writing this,
I’ve got next session chalked up in 18 minutes, need to get to the
queue to see if my 15-minute experience still holds.)&lt;/p&gt;

&lt;h2 id=&quot;crowd-&quot;&gt;Crowd 🤷&lt;/h2&gt;

&lt;p&gt;I have not heard of any official statement on number of attendees, but
&lt;strong&gt;this conference is crowded&lt;/strong&gt;, at least in Venetian and Aria (the
main sites). It’s not yet elbow-in-your-mouth-crowded, but I’ve seen a
lot of lock-step marching in and out of places, bottleneck routes
getting really congested.&lt;/p&gt;

&lt;p&gt;So, not as terrible to make me skip sessions or venues, but definitely
more crowded venues — even with people spread over multiple
locations — than in 2012/13.&lt;/p&gt;

&lt;p&gt;The other consequence is that &lt;strong&gt;you are extremely unlikely to run into
a specific person without explicit arrangements&lt;/strong&gt; — I am pretty sure
I met 80% of all Finnish attendees in those earlier
conferences. While, in general, conferences are bad places of
“&lt;em&gt;trying&lt;/em&gt; to meet someone”, I find the extremely unlikelihood of such
accidental meets (of people I know are here) somehow distancing,
making me feel more detached from others.&lt;/p&gt;

&lt;h2 id=&quot;wifi-&quot;&gt;Wifi 😢&lt;/h2&gt;

&lt;p&gt;Between absolutely horrible to passable. Superbly frustrating when you
can ping 8.8.8.8, but nothing else seems to pass through to the
Internet.&lt;/p&gt;

&lt;p&gt;Since I don’t have a local SIM — and did not pay for the 2 GB
USA-specific package from my home operator — I can’t even fall back
to mobile data.&lt;/p&gt;

&lt;p&gt;Which brings me back to this:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;
  &lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Hey &lt;a href=&quot;https://twitter.com/AWSreInvent?ref_src=twsrc%5Etfw&quot;&gt;@AWSreInvent&lt;/a&gt;,
imagine the following scenario:&lt;br /&gt;&lt;br /&gt;1) go to registration&lt;br /&gt;2)
open app for QR code&lt;br /&gt;3) app requires re-login&lt;br /&gt;4) login requires
net&lt;br /&gt;5) wifi password in app&lt;br /&gt;6) no data roaming ($$$/MB for
non-US SIM)&lt;br /&gt;&lt;br /&gt;Wifi pwd prominently++, plz?&lt;br /&gt;&lt;br /&gt;(Registration
painless w/o QR though.)&lt;/p&gt;
  &lt;p&gt;— Santeri Paavolainen (@paavolainen)
&lt;a href=&quot;https://twitter.com/paavolainen/status/1066890425737375744?ref_src=twsrc%5Etfw&quot;&gt;26. marraskuuta
2018&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;Catch-22.&lt;/p&gt;

&lt;h2 id=&quot;length-&quot;&gt;Length 🤔&lt;/h2&gt;

&lt;p&gt;I think — again, based on my memory, too &lt;strike&gt;lazy&lt;/strike&gt;tired
to check — the earlier ones were three days plus a half day for
partner summit. This is a bit of a ±0 thing as more days = more
content, but also more days = more difficult to schedule such a long
trip. This trip eats two whole weekends for traveling here and back.&lt;/p&gt;

&lt;h2 id=&quot;improvements-&quot;&gt;Improvements 🙋&lt;/h2&gt;

&lt;p&gt;Not all is meh. There are some things that I see as improvements over
my previous visits, and some things that I’ve heard from attendees as
improved from last year.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Lots of guides and helpers — not sure where is something? There’s
practically &lt;strong&gt;all the time&lt;/strong&gt; literally a highly visible guide within
20 paces of you. While the number of staff seems excessive at times,
they are definitely helpful and useful. I realized I’ve come to
almost completely on them instead of even trying to check
the venue map on the flaky wifi.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Better transport than last year. I wasn’t here last year, but people
who were said it was absolutely horrible last year. I understood
that last year the shuttle buses were doing a circular route over
all the locations — and this year they were point-to-point.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Overflows. These are screen-and-wireless-headphones combination in
most (all?) locations. Some sessions are marked as OVERFLOW and
these can be viewed from any of these overflow locations. (I don’t
get the terminology though. Overflow in different location? Overflow
to?)&lt;/p&gt;

    &lt;p&gt;I only today realized how useful this was when instead of trying to
go to a session and &lt;em&gt;then&lt;/em&gt; jump on a shuttle to next location, I
could do the other way around and use the overflow at the &lt;em&gt;other&lt;/em&gt;
location to watch the session at the place where I just left!
Doesn’t maybe make sense initially, but when you factor in lunch,
travel time etc. it ended up being much easier this way.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;overall&quot;&gt;Overall&lt;/h2&gt;

&lt;p&gt;Almost all people I discussed about the size of the conference agreed
that re:Invent is too big, multiple venues is pain and so on. This
included several AWS staff, too.&lt;/p&gt;

&lt;p&gt;How to fix? AWS Summits are clearly a way forward, maybe they could be
developed and promoted further, turn them from one-day events to
two-day events? Have them more frequently and all over the globe,
so there would be no incentive to attend &lt;em&gt;every&lt;/em&gt; one of nearby ones?&lt;/p&gt;

&lt;p&gt;Move re:Invent to another, more compact location?&lt;/p&gt;

&lt;p&gt;Make all sessions remotely viewable live? Live for a fee, some time
later free. You’ve already got overflows, which are live, so the
capability is there. (Maybe overflows are a PoC?)&lt;/p&gt;

&lt;p&gt;Split re:Invent into differently focused conferences? While a large
portion of the services are generic and useful in different
situations, I can imagine it would be possible to create some
differentiations that could act as a divider. Enterprise (migrations,
governance, services more relevant to enterprises, etc. etc.)
vs. technology focus (less governance, more startup-ey)?&lt;/p&gt;

&lt;p&gt;I don’t know. This is not purely a logistical problem, these big
conferences (just think of Microsoft and Apple) serve also other goals
than just &lt;strike&gt;wine and dine&lt;/strike&gt; &lt;strike&gt;entertain&lt;/strike&gt;
educate the attendees.&lt;/p&gt;

&lt;p&gt;(I planned this to be a short post. Better stop right n&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;(You can see all posts from re:Invent 2018 hunting down the
&lt;a href=&quot;/tags.html#reinvent2018-ref&quot;&gt;reinvent2018&lt;/a&gt; tag.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>re re:Invent</title>
   <link href="http://santtu.iki.fi/2018/11/25/reinvent"/>
   <updated>2018-11-25T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/11/25/reinvent</id>
   <content type="html">&lt;p&gt;I have attended AWS re:Invent conference twice, in 2012 and 2013. This
year as the &lt;em&gt;Head of AWS Business&lt;/em&gt; from &lt;a href=&quot;https://fiareconsulting.com/en/home/&quot;&gt;Fiare
Consulting&lt;/a&gt; will mark my third
visit to the conference.&lt;/p&gt;

&lt;p&gt;During the conference I’ll be
&lt;a href=&quot;https://twitter.com/paavolainen&quot;&gt;tweeting&lt;/a&gt;, posting some stuff here
and potentially also in my &lt;a href=&quot;https://www.linkedin.com/in/paavolainen&quot;&gt;LinkedIn
feed&lt;/a&gt;. I do not have high
expectations of visibility, so you can read these posts in different
media as sort of a process where I collate my conference experiences
and try to understand them better in my own context. If someone finds
these useful, that’s nice too.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I flew in through Arlanda — how probable is it you are sitting
next to &lt;strong&gt;another senior&lt;/strong&gt; from &lt;strong&gt;another consultancy&lt;/strong&gt; going to the
&lt;strong&gt;same conference&lt;/strong&gt;? Empirically: not zero.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I flew in already on Saturday, giving me Sunday to adjust to the time
difference. While it is sometimes possible to avoid full timezone
adjustment, re:Invent is such an intensive event that it is necessary
to be full physical and mental strength, and that’s why I reserved a
day for that. (I also exercised heavily by hiking to Turtle Head Peak
in Red Rock Canyon, and got fresh air and plenty of exposure to sun,
all of that helping the body to adjust.)&lt;/p&gt;

&lt;p&gt;Anyway, this conference has gotten bigger and bigger. While I cannot
remember exact numbers out of my head, it almost doubled from 2012 to
2013 (from several thousands to almost ten thousand, if my memory
serves correctly). Last year it was
&lt;a href=&quot;https://aws.amazon.com/blogs/aws/reinvent-2018-is-coming-are-you-ready/&quot;&gt;43 000&lt;/a&gt;
and probably quite a few more this time.&lt;/p&gt;

&lt;p&gt;While re:Invent &lt;strong&gt;was&lt;/strong&gt; smaller way way back, and while it was
definitely more compact (all of it fit in the Sands expo centre),
let’s not get too nostalgic: &lt;strong&gt;it was big even five years ago&lt;/strong&gt;. There
was absolutely no way you could attend all of the interesting sessions
nor meet all the people you thought you’d want to meet! The fact that
there are now even more sessions, spread over multiple locations on
the Strip does make some practical things harder — but “seeing all”
was back then as impossible as it is today.&lt;/p&gt;

&lt;p&gt;I have other comments to come, but I’ll cut this post short and just
get it out.&lt;/p&gt;

&lt;p&gt;(You can see all posts from re:Invent 2018
following the &lt;a href=&quot;/tags.html#reinvent2018-ref&quot;&gt;reinvent2018&lt;/a&gt; tag.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Life is short, why URLs long?</title>
   <link href="http://santtu.iki.fi/2018/06/26/shorter-urls-in-energy-simulator"/>
   <updated>2018-06-26T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/06/26/shorter-urls-in-energy-simulator</id>
   <content type="html">&lt;p&gt;At the end of last year, I wrote as part of a thesis work an &lt;a href=&quot;/2018/01/10/energy-simulator&quot;&gt;energy
market simulator&lt;/a&gt; modeling
the Finnish electricity market. While I moved onward after finishing
that work, I’ve been intending to return to the project to fix a few
of the nagging TODO items.&lt;/p&gt;

&lt;p&gt;So, while taking a look at that I also noticed that copy-pasting URLs
from the simulator did not work anymore. Ouch!&lt;/p&gt;

&lt;p&gt;But why is this a problem? The simulator has a few interesting
implementation details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It runs completely in the browser — the Monte Carlo simulation
runs as a web worker in the browser.&lt;/li&gt;
  &lt;li&gt;It is written in Scala (not JavaScript). Actually, it uses Scala.JS
which generates JavaScript from Scala sourcecode (while being mostly
cross-compilable to JVM too).&lt;/li&gt;
  &lt;li&gt;There is &lt;strong&gt;no backend and thus no state stored in any backend&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;All of the simulation world state (those user can manipulate) is
&lt;strong&gt;encoded in the URL&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is intended to make two things possible:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you do modifications on the world state and bookmark the page,
then loading the bookmark will get you the &lt;strong&gt;modified&lt;/strong&gt; world and
not the default one.&lt;/li&gt;
  &lt;li&gt;You can share the URLs, as opening the URL will get the same world
state as you had.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;something-broke&quot;&gt;Something broke&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;I have been exclusively testing this on Chrome and I do not make any
claims or attempts about whether the application works on any other
browser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Late last year the URL copying worked. When I tested it a few weeks
back, it did not. Something had changed in Chrome. Or OS X. (I checked
Chrome changelogs from last December but could not find anything
immediately obvious.)&lt;/p&gt;

&lt;p&gt;Regardless of the cause, I wanted to make URL copying work again.&lt;/p&gt;

&lt;h2 id=&quot;solutions-so-many-solutions-to-choose-from&quot;&gt;Solutions, so many solutions to choose from!&lt;/h2&gt;

&lt;p&gt;This was a problem I had considered before, and knew the solution to
that already: &lt;em&gt;encode only changes&lt;/em&gt; from the default world state. So,
what to use? Since the original (&lt;em&gt;“version 1”&lt;/em&gt;) data encoding scheme
dumped the whole world state as base64-encoded JSON, a reasonable step
might have been using JSON diffs — but no, I could not find
reasonable Scala.JS-compatible implementations. Also, many “JSON diffs”
looked quite verbose and might not have actually solved the problem at
all.&lt;/p&gt;

&lt;p&gt;Maybe if I encoded the world state as binary JSON (BSON) instead?
Alas, I did not find libraries with sufficient Scala.JS support.&lt;/p&gt;

&lt;p&gt;No automated luck this time. Let’s roll our own then!&lt;/p&gt;

&lt;p&gt;Since the UI only allows users to change the enabled/disabled state
and capacity or sources and lines and they have unique ids, it is
possible to make a short cut and only encode changes from the default
value on an identifier-by-identifier basis. So I wrote a JSON
encoder/decoder wrapper for a class that encapsulates such changes.&lt;/p&gt;

&lt;p&gt;So now the default world state URL is small since there are only some
metadata encoded (no changes to encode). Then, toggle all and change
capacities (using the global toggles and sliders) and … too long
URL. Can’t copy paste. &lt;em&gt;Damn&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;JSON ends up too verbose in this case. Partially this is also due to
the encoder/decoder logic which maps a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case class Change(name:
String, version: Int, changes: Seq[Change])&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&quot;name&quot;: ...,
&quot;version&quot;:, ..., &quot;changes&quot;: [...]}&lt;/code&gt; where each change repeats the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;version&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changes&lt;/code&gt; strings in verbatim. I could have
changed to encode the changes as an array (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[id,enabled,capacity]&lt;/code&gt;)
but… decided not to.&lt;/p&gt;

&lt;p&gt;I decided to go for a binary encoding directly. BSON was not an
option, so what others? &lt;a href=&quot;https://msgpack.org/&quot;&gt;MsgPack&lt;/a&gt; would have
been nice, since it at least has a specification and some
cross-platform support, but again, I did not find a ScalaJS-compatible
implementation that I was happy with.&lt;/p&gt;

&lt;p&gt;There are quite a few binary encoders supporting Scala.JS. Out of
those, I settled on &lt;a href=&quot;https://boopickle.suzaku.io/&quot;&gt;BooPickle&lt;/a&gt;. With
that I got the worst case data encoded as (I’ve broken it to lines of
80 characters, in reality this is all a single unbroken string):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#2-AAVTdW9taQFTAApjZW50ZXItb2lsAgACgJwADmNlbnRlci1vaWwtY2hwAgABAAtjZW50ZXItd2luZ
AIAAorIAApjZW50ZXItYmlvAgABAA5jZW50ZXItYmlvLWNocAIAAobGAAtjZW50ZXItY29hbAIAAQALY
2VudGVyLXBlYXQCAAKBnQAPY2VudGVyLXBlYXQtY2hwAgACiFAADGNlbnRlci1oeWRybwIAAoXrAA5jZ
W50ZXItbnVjbGVhcgIAAQAKY2VudGVyLWdhcwIAAQAOY2VudGVyLWdhcy1jaHACAAKA-wAMY2VudGVyL
W90aGVyAgABABBjZW50ZXItb3RoZXItY2hwAgACgSsADGNlbnRlci1zb2xhcgIAAQAId2VzdC1vaWwCA
AKDNgAMd2VzdC1vaWwtY2hwAgACTAAJd2VzdC13aW5kAgACiQUACHdlc3QtYmlvAgABAAx3ZXN0LWJpb
y1jaHACAAKCTQAJd2VzdC1jb2FsAgAChhYADXdlc3QtY29hbC1jaHACAAKH-wAJd2VzdC1wZWF0AgABA
A13ZXN0LXBlYXQtY2hwAgAChOsACndlc3QtaHlkcm8CAAKHjQAMd2VzdC1udWNsZWFyAgACoCCsAAh3Z
XN0LWdhcwIAAQAMd2VzdC1nYXMtY2hwAgAChYMACndlc3Qtb3RoZXICAAEADndlc3Qtb3RoZXItY2hwA
gACgIAACndlc3Qtc29sYXICAAIOAAlub3J0aC1vaWwCAAIhAApub3J0aC13aW5kAgACi2AACW5vcnRoL
WJpbwIAAQANbm9ydGgtYmlvLWNocAIAAoN4AApub3J0aC1jb2FsAgABAApub3J0aC1wZWF0AgABAA5ub
3J0aC1wZWF0LWNocAIAAoPJAAtub3J0aC1oeWRybwIAAqAfjwANbm9ydGgtbnVjbGVhcgIAAQAJbm9yd
GgtZ2FzAgABAAtub3J0aC1vdGhlcgIAAQALbm9ydGgtc29sYXICAAEACXNvdXRoLW9pbAIAAoLlAApzb
3V0aC13aW5kAgACgQ4ACXNvdXRoLWJpbwIAAQANc291dGgtYmlvLWNocAIAAoZGAApzb3V0aC1jb2FsA
gABAA5zb3V0aC1jb2FsLWNocAIAAqAQSAAKc291dGgtcGVhdAIAAQAOc291dGgtcGVhdC1jaHACAAKBR
wALc291dGgtaHlkcm8CAAKEHgANc291dGgtbnVjbGVhcgIAAqASuwAJc291dGgtZ2FzAgABAA1zb3V0a
C1nYXMtY2hwAgACjkIAC3NvdXRoLW90aGVyAgABAA9zb3V0aC1vdGhlci1jaHACAAKCKwALc291dGgtc
29sYXICAAITAAhlYXN0LW9pbAIAAoMLAAllYXN0LXdpbmQCAAJjAAhlYXN0LWJpbwIAAQAMZWFzdC1ia
W8tY2hwAgAChnAACWVhc3QtY29hbAIAAQAJZWFzdC1wZWF0AgABAA1lYXN0LXBlYXQtY2hwAgACg-oAC
mVhc3QtaHlkcm8CAAKG9QAMZWFzdC1udWNsZWFyAgABAAhlYXN0LWdhcwIAAQAMZWFzdC1nYXMtY2hwA
gACIQAKZWFzdC1vdGhlcgIAAQAOZWFzdC1vdGhlci1jaHACAAJ2AAplYXN0LXNvbGFyAgABAAp3ZXN0L
XNvdXRoAQKgNB0AC3dlc3QtY2VudGVyAQKgNB0ACnNvdXRoLWVhc3QBAqA0HQAMc291dGgtY2VudGVyA
QKgNB0AC2Vhc3QtY2VudGVyAQKgNB0ADGNlbnRlci1ub3J0aAECoDQdABNzd2VkZW4tbm9ydGgtaW1wb
3J0AQKH0AASc3dlZGVuLXdlc3QtaW1wb3J0AQKGQAAScnVzc2lhLWVhc3QtaW1wb3J0AQKGxQATbm9yd
2F5LW5vcnRoLWltcG9ydAECgIQAFGVzdG9uaWEtc291dGgtaW1wb3J0AQKFNQ==
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s 1950 characters. Not bad! That actually we can copy and
paste. (That’s also what is a “version 2” of the data format.)&lt;/p&gt;

&lt;p&gt;Yet it is possible to do much, much better. Here is the same URL
encoded in “version 3” format:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#3-AAVTdW9taQFTCAIAAoCcCQIAAQ8CAAKKyAACAAEBAgAChsYCAgABDAIAAoGdDQIAAohQBQIAAoXrB
wIAAQMCAAEEAgACgPsKAgABCwIAAoErDgIAAU8CAAKDNlACAAJMVwIAAokFRgIAAUcCAAKCTUkCAAKGF
koCAAKH-1MCAAFUAgAChOtNAgACh41OAgACoCCsSwIAAUwCAAKFg1ECAAFSAgACgIBVAgACDicCAAIhL
AIAAotgIQIAASICAAKDeCMCAAEpAgABKgIAAoPJJQIAAqAfjyYCAAEkAgABKAIAASsCAAE7AgACguVBA
gACgQ4xAgABMgIAAoZGNAIAATUCAAKgEEg-AgABPwIAAoFHOQIAAoQeOgIAAqASuzcCAAE4AgACjkI8A
gABPQIAAoIrQAIAAhMYAgACgwseAgACYxACAAERAgAChnATAgABGwIAARwCAAKD6hYCAAKG9RcCAAEUA
gABFQIAAiEZAgABGgIAAnYdAgABVgECoDQdSAECoDQdNgECoDQdMwECoDQdEgECoDQdBgECoDQdQgECh
9BEAQKGQC8BAobFLQECgIQfAQKFNQ==
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only 591 characters! Yet it encodes exactly the same information. How
is that possible?&lt;/p&gt;

&lt;p&gt;The world data is named and versioned with the assumption that any
structural change will result in a new version number. This means that
all source and line identifiers in the model are static and sorting
the identifiers will result in a sequence where a particular
identifier will stay at the same index! The version 3 data format uses
this fact to turn identifier into integers. This helps a lot since the
identifiers are actually pretty long (descriptive) strings.&lt;/p&gt;

&lt;p&gt;I kept support for the older formats in the code, so if you had a
version 1 encoded URL and can get your browser to open it, it should
still work. Similarly you can try to open &lt;a href=&quot;http://energysim.kooma.net/#2-AAVTdW9taQFTAApjZW50ZXItb2lsAgACgJwADmNlbnRlci1vaWwtY2hwAgABAAtjZW50ZXItd2luZAIAAorIAApjZW50ZXItYmlvAgABAA5jZW50ZXItYmlvLWNocAIAAobGAAtjZW50ZXItY29hbAIAAQALY2VudGVyLXBlYXQCAAKBnQAPY2VudGVyLXBlYXQtY2hwAgACiFAADGNlbnRlci1oeWRybwIAAoXrAA5jZW50ZXItbnVjbGVhcgIAAQAKY2VudGVyLWdhcwIAAQAOY2VudGVyLWdhcy1jaHACAAKA-wAMY2VudGVyLW90aGVyAgABABBjZW50ZXItb3RoZXItY2hwAgACgSsADGNlbnRlci1zb2xhcgIAAQAId2VzdC1vaWwCAAKDNgAMd2VzdC1vaWwtY2hwAgACTAAJd2VzdC13aW5kAgACiQUACHdlc3QtYmlvAgABAAx3ZXN0LWJpby1jaHACAAKCTQAJd2VzdC1jb2FsAgAChhYADXdlc3QtY29hbC1jaHACAAKH-wAJd2VzdC1wZWF0AgABAA13ZXN0LXBlYXQtY2hwAgAChOsACndlc3QtaHlkcm8CAAKHjQAMd2VzdC1udWNsZWFyAgACoCCsAAh3ZXN0LWdhcwIAAQAMd2VzdC1nYXMtY2hwAgAChYMACndlc3Qtb3RoZXICAAEADndlc3Qtb3RoZXItY2hwAgACgIAACndlc3Qtc29sYXICAAIOAAlub3J0aC1vaWwCAAIhAApub3J0aC13aW5kAgACi2AACW5vcnRoLWJpbwIAAQANbm9ydGgtYmlvLWNocAIAAoN4AApub3J0aC1jb2FsAgABAApub3J0aC1wZWF0AgABAA5ub3J0aC1wZWF0LWNocAIAAoPJAAtub3J0aC1oeWRybwIAAqAfjwANbm9ydGgtbnVjbGVhcgIAAQAJbm9ydGgtZ2FzAgABAAtub3J0aC1vdGhlcgIAAQALbm9ydGgtc29sYXICAAEACXNvdXRoLW9pbAIAAoLlAApzb3V0aC13aW5kAgACgQ4ACXNvdXRoLWJpbwIAAQANc291dGgtYmlvLWNocAIAAoZGAApzb3V0aC1jb2FsAgABAA5zb3V0aC1jb2FsLWNocAIAAqAQSAAKc291dGgtcGVhdAIAAQAOc291dGgtcGVhdC1jaHACAAKBRwALc291dGgtaHlkcm8CAAKEHgANc291dGgtbnVjbGVhcgIAAqASuwAJc291dGgtZ2FzAgABAA1zb3V0aC1nYXMtY2hwAgACjkIAC3NvdXRoLW90aGVyAgABAA9zb3V0aC1vdGhlci1jaHACAAKCKwALc291dGgtc29sYXICAAITAAhlYXN0LW9pbAIAAoMLAAllYXN0LXdpbmQCAAJjAAhlYXN0LWJpbwIAAQAMZWFzdC1iaW8tY2hwAgAChnAACWVhc3QtY29hbAIAAQAJZWFzdC1wZWF0AgABAA1lYXN0LXBlYXQtY2hwAgACg-oACmVhc3QtaHlkcm8CAAKG9QAMZWFzdC1udWNsZWFyAgABAAhlYXN0LWdhcwIAAQAMZWFzdC1nYXMtY2hwAgACIQAKZWFzdC1vdGhlcgIAAQAOZWFzdC1vdGhlci1jaHACAAJ2AAplYXN0LXNvbGFyAgABAAp3ZXN0LXNvdXRoAQKgNB0AC3dlc3QtY2VudGVyAQKgNB0ACnNvdXRoLWVhc3QBAqA0HQAMc291dGgtY2VudGVyAQKgNB0AC2Vhc3QtY2VudGVyAQKgNB0ADGNlbnRlci1ub3J0aAECoDQdABNzd2VkZW4tbm9ydGgtaW1wb3J0AQKH0AASc3dlZGVuLXdlc3QtaW1wb3J0AQKGQAAScnVzc2lhLWVhc3QtaW1wb3J0AQKGxQATbm9yd2F5LW5vcnRoLWltcG9ydAECgIQAFGVzdG9uaWEtc291dGgtaW1wb3J0AQKFNQ==&quot;&gt;this
URL&lt;/a&gt;. If
you manipulate the model in any way (try toggling a checkbox) it will
convert the URL into version 3 format (&lt;a href=&quot;http://energysim.kooma.net/#3-AAVTdW9taQFTCAIAAoCcCQIAAQ8CAAKKyAACAAEBAgAChsYCAgABDAIAAoGdDQIAAohQBQIAAoXrBwIAAQMCAAEEAgACgPsKAgABCwIAAoErDgIAAU8CAAKDNlACAAJMVwIAAokFRgIAAUcCAAKCTUkCAAKGFkoCAAKH-1MCAAFUAgAChOtNAgACh41OAgACoCCsSwIAAUwCAAKFg1ECAAFSAgACgIBVAgACDicCAAIhLAIAAotgIQIAASICAAKDeCMCAAEpAgABKgIAAoPJJQIAAqAfjyYCAAEkAgABKAIAASsCAAE7AgACguVBAgACgQ4xAgABMgIAAoZGNAIAATUCAAKgEEg-AgABPwIAAoFHOQIAAoQeOgIAAqASuzcCAAE4AgACjkI8AgABPQIAAoIrQAIAAhMYAgACgwseAgACYxACAAERAgAChnATAgABGwIAARwCAAKD6hYCAAKG9RcCAAEUAgABFQIAAiEZAgABGgIAAnYdAgABVgECoDQdSAECoDQdNgECoDQdMwECoDQdEgECoDQdBgECoDQdQgECh9BEAQKGQC8BAobFLQECgIQfAQKFNQ==&quot;&gt;like
this&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you are interested in the code, you can find it
&lt;a href=&quot;https://github.com/santtu/energysim/blob/8d2daec02d3ffd8e4148cd3e1fda2356c6e0a0c1/ui/src/main/scala/fi/iki/santtu/energysimui/Main.scala#L163&quot;&gt;here&lt;/a&gt;
(I linked a commit version since I might refactor the code later).&lt;/p&gt;

&lt;p&gt;P.S. If you are bothered because of inconsistent indentation, it is
caused by me sometimes editing the code in IntelliJ IDEA and sometimes
in Emacs (with ENSIME). I strongly refrain from re-indenting source
files on a whim as it breaks a lot of version history tracking, even
on my own source code. As a professional programmer I have learned a
long time ago to check in my own ego (regarding indentation and code
style) at the door and insead adjust to the style of the codebase
currently being worked on.&lt;/p&gt;

&lt;p&gt;So if you are a junior: &lt;span style=&quot;color: red&quot;&gt;Don’t be an
ass&lt;/span&gt; — don’t arbitrarily re-style existing code to your own
tastes. Touch only the code you actually work on.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Energy Simulator</title>
   <link href="http://santtu.iki.fi/2018/01/10/energy-simulator"/>
   <updated>2018-01-10T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2018/01/10/energy-simulator</id>
   <content type="html">&lt;p&gt;&lt;small&gt;(I have been quiet on this blog for quite a while. I might
offer an explanation on that at some point. Although, some of the
reasons can be found in this blog post.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;During the latter part of 2017 I worked on my bachelor’s thesis on
Engineering Physics at the Aalto University&lt;sup id=&quot;fnref:degrees&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:degrees&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. You can find
the results online (with a short description and a link back to
&lt;strong&gt;this&lt;/strong&gt; article) at &lt;a href=&quot;http://energysim.kooma.net&quot;&gt;energysim.kooma.net&lt;/a&gt;
and &lt;a href=&quot;https://github.com/santtu/energysim&quot;&gt;GitHub&lt;/a&gt;. If you want to play
with the result, click on the first one, and if you are interested in
the code and not on a pretty long monologue, click on the second one.&lt;/p&gt;

&lt;p&gt;Also, in case you want to get really sciency, just jump to reading
&lt;a href=&quot;/assets/posts/energy-simulation-report.pdf&quot;&gt;the actual B.Sc. thesis&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;There’s this thing called &lt;strong&gt;energy policy&lt;/strong&gt;. You might not know it
even exists, yet it affects you every day. Each country has one, even
if it is only implicit in the set of current policies enacted by the
government. Energy policy essentially defines the set of goals of how
energy is produced and used by a country, and the set of rules that
aim to get those goals accomplished. In the olden days, energy
policies were mostly about economics and safety of the energy
supply. Nowadays, a third axis of environmental effects must be taken
into account (especially greenhouse gases, but also particulate
emissions et al).&lt;/p&gt;

&lt;p&gt;Even countries neighbouring each other can have vastly different
energy policies that reflect their own, particular local
environment. Norway, for example, has a huge natural advantage of
having lots of water and mountains. When these two are mixed, these
result in lots and lots of hydroelectric power. So while Norway is a
&lt;strong&gt;major&lt;/strong&gt; oil producer, it produces almost all of its electricity from
&lt;strong&gt;water&lt;/strong&gt;. Contrast this with France, which has taken a completely
different approach having over 70% of its electricity producer through
nuclear power. So overall, without going too much into the why’s of
energy policy, let’s just say that policies differ from country to
country, and there’s usually good reasons beneath the differences.&lt;/p&gt;

&lt;p&gt;Also, while I’ll primarily will talk about &lt;strong&gt;electricity&lt;/strong&gt;, please
note that “energy use” includes also the production and use of heat
(pretty important in colder climates), industrial uses and
transportation.&lt;/p&gt;

&lt;h2 id=&quot;finland&quot;&gt;Finland&lt;/h2&gt;

&lt;p&gt;So, when concentrating on my own country, Finland, and its energy
policy, one finds many interesting and conflicting drivers. At the
moment, simply put, Finland is dependent on electricity imports. The
peak electricity production in Finland is &lt;strong&gt;less than the peak
demand&lt;/strong&gt;&lt;sup id=&quot;fnref:jaaskelainen&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:jaaskelainen&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Whether this is a problem &lt;strong&gt;right now&lt;/strong&gt; is up
to debate, and it may even be possible that in the future the problem
will be solved through an unified all-EU electricity market. However,
things move pretty slowly in the electricity market, thus any external
beneficial effects are likely to be even more slow than any local
energy policy effects (it takes easily decades to build GWs of
production capacity&lt;sup id=&quot;fnref:ol3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ol3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;

&lt;p&gt;Energy policy, pretty much by its definiton will be closely tied with
politics, which in turn ties into popular opinion. I do not know about
other countries, but at least here in Finland there are several trends
affecting the attitude towards energy policy in the general
population: polarization, loss of interest, lack of trust and
unrealistic production method preferences:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There’s a widening attitude gap between rural and urban
population. While the majority of Finland’s population is urban
(&amp;gt;80%), due to historical reasons the rural population has a larger
say in domestic politics than would be immediately obvious. For this
reason, these differences cannot be disregarded.&lt;/li&gt;
  &lt;li&gt;Some segments (read: the same segment that fancies any popular
politic, e.g. white, male etc. etc.) are becoming jaded with the
complexities of energy policies (yearning back to the times when you
could just burn oil without any care in the world?), and of course,
if the trend gains more traction will make any kind of rational
energy policy more and more difficult as it is hijacked by popular
politics.&lt;/li&gt;
  &lt;li&gt;There’s a marked lack of trust by the general public on politicians
(on energy policies), of energy companies … also there are
examples in Finland of politicians strongly dismissing energy and
policy experts. Not good, of course.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unless you’ve lived under a rock, you should have seen where popular
politics combined with ignorance of facts can lead. So, ignorance,
not a good thing. What can be done about it?&lt;/p&gt;

&lt;h2 id=&quot;show-dont-tell&quot;&gt;Show, don’t tell&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I think that people are more receptive towards results they have
experienced through their own actions.&lt;/em&gt; What if people could play out
their own energy policy preferences out, and see how that would affect
CO₂ emissions and the safety of electricity supply? Out of this
thought resulted the &lt;em&gt;Energy Simulator&lt;/em&gt; (or more accutarely,
electricity sandbox simulation of Finland but the shorter, albeit less
accurate version has stuck). Show below are two different situations,
first the default state, and another with some … issues:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/energy-simulator-cases.png&quot;&gt;&lt;img src=&quot;/assets/posts/energy-simulator-cases.png&quot; alt=&quot;Energy simulator with two setups, one with default values and another with less than optimal values&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Energy simulator running after running some time with
defaults (left) and several imports disabled and production
capacitities disabled or reduced (right). Light green indicate some
regional blackouts and redder colours more frequent blackouts. The CO₂
emissions on the latter are 120% higher than in the former case.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;You can go ahead and play with the energy simulator
at &lt;a href=&quot;http://energysim.kooma.net/&quot;&gt;&lt;strong&gt;energysim.kooma.net&lt;/strong&gt;&lt;/a&gt;. I’ll talk a
bit more about the technical details below and if you are so inclined,
you can check out the source code
at
&lt;a href=&quot;https://github.com/santtu/energysim&quot;&gt;github.com/santtu/energysim&lt;/a&gt;. You
can find also a lot more background information on Finland’s energy
situation, on how the energy simulator’s simulation and its parameters
are modeled in
my &lt;a href=&quot;/assets/posts/energy-simulation-report.pdf&quot;&gt;Bachelor’s thesis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ll quickly touch on some non-technical issues, but after that I’ll
go more into the technical details of the implementation. You can skip
rest of the post if you’re not into programming (well, after some
other stuff first).&lt;/p&gt;

&lt;p&gt;While the energy simulator is nice in itself, it is &lt;strong&gt;not a game&lt;/strong&gt; as
it currently stands. It is an open-ended sandbox simulation, and it
has lots of caveats and shortcomings due to all of the necessary
abstraction and simplification that just getting it finished in
limited time required.&lt;/p&gt;

&lt;p&gt;Likewise the hypothesis that using a “game” (which this, strictly
speaking is not) would be more effective in changing people’s
attitudes on energy policy towards more “holistic” approach (from
where? from assumed polarized ends?) is entirely unverified. I thought
about adding a questionnaire before and after, but finally decided to
omit it simply because of schedule (results would not have made into
the BSc report).&lt;/p&gt;

&lt;p&gt;And finally, &lt;strong&gt;I am not an UX designer&lt;/strong&gt; and either not very good at
CSS or web layouts. There are tons of elements that I dislike yet I
could not justify myself for spending hours and hours on polishing it
from “engineering quality” to “professional quality”, especially when
I needed to finish first other things more relevant from the
scientific point of view. In the end, it got finished, and I have
other things to do. Time to move on and accept it as whatever it
currently is.&lt;/p&gt;

&lt;h2 id=&quot;lets-get-technical&quot;&gt;Let’s get technical&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Monte Carlo simulation.&lt;/strong&gt; The simulation is a stochastic
simulation that, for each simulation round, draws random samples of
capacities for consumption and production values&lt;sup id=&quot;fnref:transmission&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:transmission&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Edmonds-Karp maximum flow algorithm&lt;/strong&gt; is used iteratively to
distribute electricity (from surplus production areas) in a way that
minimises &lt;strong&gt;global CO₂ emissions&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Everything runs in the browser.&lt;/strong&gt; This is a pure single-page
application, with everything running in the browser including the
sandbox simulation. The simulation runs in a separate web worker
thread so it doesn’t block the user interface.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Scala all the way down.&lt;/strong&gt; While the browser runs javascript, the
whole energy simulator – simulator core, web worker and user
interfae – are all written in Scala.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;All state in the URL.&lt;/strong&gt; The URL contains always contains the
current model. You can copy and paste the URL for
others. Uuuuunfortunately the URL is also several kilobytes in size
and that might potentially be a teeny little problem with some
browsers…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use of Monte Carlo simulation came quite naturally as most of the
source data is experimental (e.g. real world) and not expressable as a
mathematical expression. This meant that performing any kind of
mathematical analysis to infer the overall properties of the system
was pretty much out of the question. The use of random sampling in a
Monte Carlo simulation results in meaningful and &lt;em&gt;accurate&lt;/em&gt; statistics
in the long run. Thus after twiddling with the parameters you can let
the simulation just run and the most prominent values (mean and
standard deviation) are guaranteed to be close to what would be the
results of an analytical approach (if ever done) to within some error
margin&lt;sup id=&quot;fnref:spectral&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:spectral&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;From the very beginning I realized the simulation would need to run in
a browser. There is no way I could furnish the resources to do this
server-side! While the JVM version runs at about 500x the speed of the
JS version, there are way way way more browsers out there. I thought
about using WebCL for the simulation core to speed it up as all of the
sampling could be trivially parallelized, and even the Edmonds-Karp
algorithm probably could be ported to WebCL. However, schedules again,
and the few iterations per second I get from my old MBP on Chrome is
“good enough”.&lt;/p&gt;

&lt;p&gt;While the very first trial simulation I wrote in Python, all
subsequent development was in Scala. &lt;strong&gt;But what, didn’t this run in
the browser?&lt;/strong&gt; Yes! Thanks to the magic
of &lt;a href=&quot;https://www.scala-js.org/&quot;&gt;Scala.JS&lt;/a&gt;, all of the simulation code
works &lt;strong&gt;both&lt;/strong&gt; in JVM environment (at JVM speeds!)  &lt;strong&gt;and&lt;/strong&gt; in
JavaScript (both in browser and nodejs). Only a very small amount of
glue was needed in the actual JS-only land, although since the user
interface part does interface with browser, it is very much aware of
the javascript-isms of the browser environment (global variables and
so on).&lt;/p&gt;

&lt;p&gt;While undoubtedly the Scala.JS version of simulation is slower than a
hand-written javascript code, I considered writing code in Scala much
easier than in JavaScript. While targeting JS from Scala.JS did set
some limits on library use, for example, I think it overall offered a
much nicer environment. First of all, in the simulator core I could
run, test and debug it in scala directly. Thanks to the strong typing
of Scala I had a high confidence of it working correctly in the JS
world, too. Of course, all the unit tests on the core run in both JVM
and JS environments (nodejs for JS, not in browser). Furthermore, the
functional programming aspects made it natural to do state management,
for example — the “world model” is an immutable data structure, and
any changes result in a new version of it. Thus any point where it is
updated becomes a natural place to update the single-page application
visible (address bar) state too.&lt;/p&gt;

&lt;p&gt;I did the user interface using React bindings to Scala.JS. While it
took some time to learn their proper use (the distinction between
state, props and backend instances and what to use were not always
immediately obvious), I liked the result overall. What I came out
missing was an easier way to integrate with other (non-core) react
components. I ended up using a patched version of scalajs-react-bridge
— not an optimal solution, and the syntatic difference between
scalajs-react and scalajs-react-bridge usage is a visual irritation.&lt;/p&gt;

&lt;p&gt;While all of the model is encoded in the URL, this may result in
problems as the URL is a teeny bit long (it is Base64-encoded JSON
file). Passing the model via URL does have the benefit that it is
possible to pass URLs around. I am not sure how URL shortening
services will react to several kilobytes of URL, though…&lt;/p&gt;

&lt;p&gt;Okay, the technical bit came out as a bit of a ramble. In case you are
interested in more details, or would like to extend or re-use the
energy simulator please don’t hesitate to contact me with questions!
Also, in case you are reading this in 2020 or so you probably should
check out the &lt;a href=&quot;https://github.com/santtu/energysim&quot;&gt;repository&lt;/a&gt; first
as it &lt;em&gt;might&lt;/em&gt; be more up-to-date.&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:degrees&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not my first degree. &lt;a href=&quot;#fnref:degrees&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:jaaskelainen&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Jääskeläinen et al, &lt;em&gt;Adequacy of power capacity during winter peaks in Finland&lt;/em&gt;, DOI: &lt;a href=&quot;https://dx.doi.org/10.1109/EEM.2017.7981883&quot;&gt;10.1109/EEM.2017.7981883&lt;/a&gt; &lt;a href=&quot;#fnref:jaaskelainen&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:ol3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This can be attested by the Olkiluoto 3 nuclear power plant project which has taken over a decade longer than planned. &lt;a href=&quot;#fnref:ol3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:transmission&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Transmission line capacity is also sampled, but for simplicity they were modeled at constant capacity (e.g. no failures, no capacity variances). &lt;a href=&quot;#fnref:transmission&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:spectral&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The “MC results approach true values” argument has several requirements that are not necessarily satistfied in this case, though. The quality of the random number generator in JavaScript is questionable, for example. &lt;a href=&quot;#fnref:spectral&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Dynamic devtest deployments</title>
   <link href="http://santtu.iki.fi/2016/01/30/dynamic-devtest-deployment"/>
   <updated>2016-01-30T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2016/01/30/dynamic-devtest-deployment</id>
   <content type="html">&lt;p&gt;While I work less and less on down-to-earth development, there are
times when I get a chance to hack something. In this post I’ll
describe a devtest deployment system I got a chance to be work on.&lt;/p&gt;

&lt;p&gt;In a system we are developing we wanted to do a persistent deployment
of the whole system to &lt;a href=&quot;https://aws.amazon.com/ecs/&quot;&gt;ECS&lt;/a&gt; on each
branch repository push where each subservice would be accessible as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;branch&amp;gt;-&amp;lt;service&amp;gt;.dev.example.com&lt;/code&gt;&lt;sup id=&quot;fnref:examplecom&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:examplecom&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. This would make it
easy for developer to verify integration tests before merging (pull
request) to master&lt;sup id=&quot;fnref:integration&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:integration&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, to show their work to other
developers and to allow non-developer stakeholders easy access to
features as they are being developed.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/devtest-deployments-process.svg&quot;&gt;&lt;img src=&quot;/assets/posts/devtest-deployments-process.svg&quot; alt=&quot;Testing pipeline&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Flow of each push through the CI. Integration tests are
run against a deployment on ECS.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;There are multiple ways to accomplish this such as using dynamic DNS
updates, ELBs and so on, and after some discussions and testing we
settled on the following setup.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;There is a separate &lt;em&gt;frontend&lt;/em&gt; deployment that consists of etcd and
nginx servers.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Each branch deployment service registers itself to the frontend by
addings its address to etcd registry with its branch and service
names.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A watcher process on nginx container notices changes to etcd
registry and updates nginx configuration so that the
&lt;strong&gt;branch&lt;/strong&gt;-&lt;strong&gt;service&lt;/strong&gt;.dev address gets proxied to the correct
docker container.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/devtest-deployment-operation.svg&quot;&gt;&lt;img src=&quot;/assets/posts/devtest-deployment-operation.svg&quot; alt=&quot;Request processing in deployment&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Request processing with multiple branch deployments. Each
service registers its address and port to etcd registry.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Registration is done during service startup and is also pretty simple
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REGISTRY_URL&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SERVICE&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAME&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PORT&lt;/code&gt; are passed as Docker
environment variables, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip&lt;/code&gt; is fetched from EC2 metadata service):&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PORT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$NAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;INFO: Registering to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; as &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$NAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SERVICE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; at &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PORT&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;/v2/keys/deployment/&lt;span class=&quot;nv&quot;&gt;$NAME&lt;/span&gt;/service/&lt;span class=&quot;nv&quot;&gt;$SERVICE&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;now&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; +&lt;span class=&quot;s2&quot;&gt;&quot;%Y-%m-%dT%H:%M:%SZ&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$curl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;/ip &lt;span class=&quot;nt&quot;&gt;-XPUT&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
    &lt;span class=&quot;nv&quot;&gt;$curl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;/port &lt;span class=&quot;nt&quot;&gt;-XPUT&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PORT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
    &lt;span class=&quot;nv&quot;&gt;$curl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;/v2/keys/deployment/&lt;span class=&quot;nv&quot;&gt;$NAME&lt;/span&gt;/created &lt;span class=&quot;nt&quot;&gt;-XPUT&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$now&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly when the service is shut down it’ll issue &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELETE&lt;/code&gt; on its
keys to unregister itself.&lt;/p&gt;

&lt;p&gt;The nginx container is based on the standard docker registry &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;
container, but it will start a “regenerate” process alongside the
actual nginx server. It uses
&lt;a href=&quot;https://github.com/santtu/etcdwatch&quot;&gt;etcdwatch&lt;/a&gt; to keep track of
registry changes and then finally a separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;regenerate.py&lt;/code&gt; script
takes the registry contents and updates the nginx configuration
file&lt;sup id=&quot;fnref:regenerate&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:regenerate&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Registry is at &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Starting etcdwatch to generate configuration files&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
    etcdwatch &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$REGISTRY_URL&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /deployment &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'./regenerate.py &amp;amp;&amp;amp; nginx -s reload &amp;amp;&amp;amp; echo `date -u`: Regenerated configuration'&lt;/span&gt; &amp;amp;
    &lt;span class=&quot;nv&quot;&gt;pids&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$!&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now some caveats. &lt;strong&gt;THIS IS NOT FOR PRODUCTION USE.&lt;/strong&gt; We use this only
for devtest deployments. This setup is meant to make it easy and
straighforward to test and verify things &lt;em&gt;during development&lt;/em&gt;, even
when working on incomplete and definitely-not-ready-for-merge code
changes.&lt;/p&gt;

&lt;p&gt;I have also omitted a lot of details. Where does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PORT&lt;/code&gt; come from?
(It needs to be container’s &lt;em&gt;host port&lt;/em&gt;, and it needs to be unique per
&lt;em&gt;container instance&lt;/em&gt;.) How to use frontend also on local (developer
machine) deployment? What to use as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REGISTRY_URL&lt;/code&gt;? How to actually
integrate all of this into a CI pipeline? — I’ll leave those as a home
exercise either to solve yourself, or to pester me to write about them
:-)&lt;/p&gt;

&lt;p&gt;Anyway we are pretty happy about the setup. It means that &lt;em&gt;any&lt;/em&gt; branch
will get full integration test love on an ECS-deployed setup,
automatically and without any extra work on developer’s side. It also
means that errors and problems are a bit easier to debug, since any
URL from any log or test user report will automatically reveal branch
and service names.&lt;/p&gt;

&lt;p&gt;It is also easy to determine a correct url to pass to other people
(developers, stakeholders, internal alpha testers) as it is &lt;em&gt;always&lt;/em&gt;
&lt;strong&gt;branch&lt;/strong&gt;.dev.example.com. We special-cased the default entry point
to drop the service name.&lt;/p&gt;

&lt;p&gt;Sprint demo coming up? Merge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;demo&lt;/code&gt;, push and it’ll be up
in a jiffy.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:examplecom&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; in reality, of course. &lt;a href=&quot;#fnref:examplecom&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:integration&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Before you say that a developer should be able to run integration tests locally and tests should always match ECS-based tests thanks to the magic of docker I’ll answer that yes, they can, it’s one command, and no, since there are inherent differences in deployment in local vs. remote deployment the results are not always the same. Although usually there are no problems, and when there are they usually are configuration and not code problems. &lt;a href=&quot;#fnref:integration&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:regenerate&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The regenerate script actually just dumps the registry information to a Jinja2 template, writing the result to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d&lt;/code&gt; directory. &lt;a href=&quot;#fnref:regenerate&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>On Software Development and Layperson's Perceptions</title>
   <link href="http://santtu.iki.fi/2016/01/17/on-software-development-and-layperson-perception"/>
   <updated>2016-01-17T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2016/01/17/on-software-development-and-layperson-perception</id>
   <content type="html">&lt;p&gt;Since I have been in the “software business” for about two decades it
is natural that I project my own knowledge on to any software problem
I hear. Yet sometimes I get a glimpse of how this whole “software
thing” might look to people who have little or no knowledge at all of
software development.&lt;/p&gt;

&lt;p&gt;When I recently was complaining about a billing service (of a local
sporting association) lacking a very useful and common feature, the
reply I got gave me one of these “oh, so that’s what it looks like”
moments of insight. &lt;strong&gt;“The vendor asked too much money for the
feature.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few thoughts raced my mind.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;It just can’t be &lt;strong&gt;that&lt;/strong&gt; expensive - this must be a case of
sticker shock!&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;The system does feel a little home-brewed, maybe it is a bespoke or
tailored solution instead of COTS or SaaS?&lt;/li&gt;
  &lt;li&gt;In that case &lt;em&gt;the vendor may be trying to cover development costs of
a new feature, plus some.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Then again &lt;em&gt;the feature is pretty basic and could probably
be implemented in one day, with time to spare.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But thinking this way is just looking at trees instead of the forest.&lt;/p&gt;

&lt;p&gt;It’s not about &lt;em&gt;my&lt;/em&gt; views or &lt;em&gt;my&lt;/em&gt; estimates. I am not the customer of
the vendor. I do not make a decision here. This is a case of
information asymmetry between the vendor and their customer. My
viewpoint is more symmetric, and thus not valid in this case.&lt;/p&gt;

&lt;p&gt;What is the problem, then?&lt;/p&gt;

&lt;p&gt;Before going to the main question I have (about the forest), let me
first take a look at some trees first.&lt;/p&gt;

&lt;h2 id=&quot;estimation-is-useless-estimation-is-valuable&quot;&gt;Estimation is useless! Estimation is valuable!&lt;/h2&gt;

&lt;p&gt;While software estimation&lt;sup id=&quot;fnref:estimation&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:estimation&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; itself has been
&lt;a href=&quot;https://scholar.google.fi/scholar?q=%22software+estimation%22&amp;amp;hl=en&amp;amp;as_sdt=0%2C5&amp;amp;as_ylo=&amp;amp;as_yhi=1980&quot;&gt;studied for a long time&lt;/a&gt;,
is it even possible to estimate software development efforts in
reality? What is its place in the world of agile and lean development?&lt;/p&gt;

&lt;p&gt;I’ve seen people think that agile development has made away with
software estimation. &lt;strong&gt;It has not.&lt;/strong&gt; Task sizing, planning poker or
even just “guessimating” whether a story will fit a sprint or not &lt;em&gt;are
all judgments based on software estimation&lt;/em&gt;. Doing estimation by the
seat of the pants instead of formally does not make it go away.&lt;/p&gt;

&lt;p&gt;Software estimation is also known to go horrendously wrong. I am not
going to even link examples, it’s that depressing. […] So which is
it?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Estimating “small” problems can be done with &lt;em&gt;useful reliability and
accuracy.&lt;/em&gt;&lt;sup id=&quot;fnref:useful&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:useful&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;Estimating “large” problems is difficult because &lt;em&gt;requirements are
not known to sufficient detail&lt;/em&gt;.&lt;sup id=&quot;fnref:requirements&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:requirements&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My view is that software estimation in itself is not useless and when
used in correct context can yield usefully accurate results.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Just think about it yourself — a programmer is making
judgments about task complexity and difficulty all the time. If these
estimates were completely useless what would that mean? I mean, if
you’d estimate a ten-minute task to take five years? &lt;em&gt;You would be
bloody useless.&lt;/em&gt; And jobless, fast.&lt;/small&gt;&lt;/p&gt;

&lt;h2 id=&quot;software-is-easy-software-is-hard&quot;&gt;Software is easy! Software is hard!&lt;/h2&gt;

&lt;p&gt;I’ve written &lt;a href=&quot;/2013/10/28/life-is-easier&quot;&gt;previously&lt;/a&gt;
about the power of being able to write programs. But is software easy?
Being able to use programs for automating rote tasks just means that
it is incredibly &lt;em&gt;powerful&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Software is not easy or hard. There are hard limits to some problems
that come from either the theory of computability or from physical
limits, but software in itself is not easy or hard. &lt;em&gt;Learning how to
write software&lt;/em&gt; may be hard, or it may be easy, but this is as
meaningless as saying that learning to draw is easy or hard — some
people may have natural affinity, or the drive to learn. If so,
learning is &lt;em&gt;apparently&lt;/em&gt; easy.&lt;/p&gt;

&lt;p&gt;Most of the things we value are difficult and time-consuming to
learn. Even if some people make learning look easy.&lt;/p&gt;

&lt;p&gt;Learning to do software is hard. So is learning to play violin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yet&lt;/strong&gt; — yet I have often encountered, and I believe to be common
that many people think software is easy. “Easy” in the sense that “it
cannot take more than a few days” easy. “Easy” in the meaning that
“those people at WhizzyCorp got 1M users in two weeks” easy. “Easy” in
the suggestion “I can get a random programmer to replace your easy
job” easy. Banal, if you may.&lt;/p&gt;

&lt;p&gt;Some things that look like magic are actually easy to do in software —
now. Some things that are difficult today are easy — in the
future. This rapid change may confuse people both ways, both into
thinking that something is not possible when it actually has become
possible due to a recent development, but also equally well into
tricking people thinking that past rapid changes automatically
translate into &lt;em&gt;automatically&lt;/em&gt; making previously difficult things easy
&lt;em&gt;now&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;finally-the-forest&quot;&gt;Finally, the forest.&lt;/h2&gt;

&lt;p&gt;I think that there is a gulf between “laypeople” and “professionals”
regarding the difficulty and complexity of software development. This
is a point I find difficult to explain even to myself — this train of
thought is work in progress. I’ll try my best to articulate this
viewpoint in text now.&lt;/p&gt;

&lt;p&gt;First, this gulf is not about skills or knowledge. I have absolutely
no idea on how to construct an airplane or how much of work it
does. Yet someone does.&lt;/p&gt;

&lt;p&gt;Someone out there does not have any idea on how much work is to create
software for a Mars rover. Well, &lt;em&gt;I don’t&lt;/em&gt;, but someone at NASA does.&lt;/p&gt;

&lt;p&gt;Unfortunately software development is often bespoke or tailored
work. This means there is information asymmetry between customer and
vendor. &lt;em&gt;Even when assuming honest and ethical vendors&lt;/em&gt; this asymmetry
persists.&lt;sup id=&quot;fnref:dishonest&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:dishonest&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;So when a software professional gives an estimate — making the
assumption that it is a &lt;strong&gt;reasonably accurate estimate given the
constraints I outlined above&lt;/strong&gt; — what is a layperson e.g. the customer
to do with this estimate? There are four possibilities (SWOT anyone?)
between professional’s estimate and customer’s expectations:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Both match and are correct: nice&lt;/li&gt;
  &lt;li&gt;Estimate is correct and expectations are incorrect: customer is
happily surprised (estimate is lower) or … put into a bind
(estimate is higher)&lt;/li&gt;
  &lt;li&gt;Estimate is incorrect and expectations are correct: oh woe is me&lt;sup id=&quot;fnref:woe&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:woe&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;Both are incorrect: run, don’t look back, just run&lt;/li&gt;
&lt;/ol&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/vendor-estimates-vs-customer-expectations.svg&quot;&gt;&lt;img src=&quot;/assets/posts/vendor-estimates-vs-customer-expectations.svg&quot; alt=&quot;Customer expectations vs vendor estimates&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;/figure&gt;

&lt;p&gt;Finally, the question:&lt;/p&gt;

&lt;p class=&quot;shout&quot;&gt;
Why and how do layperson expectations and
professional estimates differ?
&lt;/p&gt;

&lt;p&gt;That’s it. That’s the forest.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s not that professionals’ estimates are incorrect.&lt;/em&gt; If estimates
are used in a valid context then they are likely to be reliable and
useful.&lt;sup id=&quot;fnref:fucknot&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:fucknot&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s not that laypeople’s estimates are incorrect&lt;/em&gt;, either. They most
likely are incorrect for the exactly same reasons that any random
person’s estimates for Mars rover software or airplane construction
work are incorrect. Vendor estimates and customer expectations are
very likely to differ. Assuming they would match is not a sensible
default.&lt;/p&gt;

&lt;p class=&quot;shout&quot;&gt;
How?
&lt;/p&gt;

&lt;p&gt;How they are going to differ? My own experience is that they are more
likely to be underestimates than overestimates. Yet I don’t consider
the &lt;em&gt;quantitative&lt;/em&gt; difference as important as the qualitative:&lt;/p&gt;

&lt;p class=&quot;shout&quot;&gt;
Why?
&lt;/p&gt;

&lt;p&gt;Why? I don’t know. I tried looking into research into software
estimation.&lt;sup id=&quot;fnref:notgood&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:notgood&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; I found papers on estimation techniques, their
validity and accuracy, comparisons between them and so on, but I did
not find anything that would consider the psychological or
sociological reasons why people (especially professionals and
non-professionals) would or could take different viewpoints or stands
on software complexity or effort estimation.&lt;/p&gt;

&lt;p&gt;I have no answers here, only questions.&lt;/p&gt;

&lt;p&gt;I think that looking into the &lt;em&gt;why&lt;/em&gt; could potentially help a lot in
the software industry’s interaction with customers. I think that the
software industry or academia is not looking enough (if at all) into
the human side — sociology and psychology — of interactions between
&lt;em&gt;humans&lt;/em&gt; in software professions and &lt;em&gt;humans&lt;/em&gt; in other professions.&lt;/p&gt;

&lt;p&gt;Why are customer requirements misunderstood? What are the warning
signs in human communication or behavior?&lt;/p&gt;

&lt;p&gt;Why customers think they have clear requirements when they are not
clear? What is an effective way to communicate the inadequacy of
requirements?&lt;/p&gt;

&lt;p&gt;And so on. Consider research into group-think, for example (Bay of Pigs
decision-making is a famous example). This is not computer science, not
computing science, not software engineering. It is cross-department
stuff. Not very popular in CS, I know&lt;sup id=&quot;fnref:refs&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:refs&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-big-conclusion&quot;&gt;The Big Conclusion&lt;/h2&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Nope, there is none.&lt;/p&gt;

&lt;p&gt;I wrote this blog post because I got a rare glimpse into
non-software-person thinking, got thinking, and found out questions I
found no answers for.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:estimation&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For an all-around view on software estimation in practice I can recommend Steve McConnell’s book &lt;a href=&quot;http://www.stevemcconnell.com/est.htm&quot;&gt;Software Estimation: Demystifying the Black Art&lt;/a&gt;. &lt;a href=&quot;#fnref:estimation&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:useful&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Meaning useful in the context of software development project. It is not uncommon to go 3x or 10x way off in estimation of tasks in a scrum sprint, for example. However agile methods have feedback processes meant to keep this deviation from ballooning uncontrollably. In this context estimations do provide metrics useful to guide development projects. &lt;a href=&quot;#fnref:useful&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:requirements&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is the crux of agile methods. While a waterfall software project could &lt;em&gt;theoretically&lt;/em&gt; be estimated accurately &lt;em&gt;given that requirements are known in advance&lt;/em&gt;, in practice nobody knows the requirements in advance (even when they think they do). Agile methods start with the assumption that requirements &lt;em&gt;will&lt;/em&gt; change. &lt;a href=&quot;#fnref:requirements&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:dishonest&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Dishonest and unethical vendors may use the asymmetry to &lt;em&gt;their own advantage&lt;/em&gt;. Yet information asymmetry can cause problems even for honest and ethical vendors and their customers. &lt;a href=&quot;#fnref:dishonest&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:woe&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;If the vendor estimate is higher, then they will not get the job and it’s their loss. If vendor’s estimate is lower, they will get the job but there will be hell later when the either the customer ends up paying more than they expect, or the vendor will go negative profit on the project. &lt;a href=&quot;#fnref:woe&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:fucknot&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Likely, likely, likely. Never 100%. &lt;a href=&quot;#fnref:fucknot&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:notgood&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I have to admit I did not do a thorough literary search. Just random searches on scholar, ieexplore, university library search portal and the like. &lt;a href=&quot;#fnref:notgood&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:refs&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;If you got here, please read &lt;a href=&quot;http://dx.doi.org/10.1109/MC.2002.999774&quot;&gt;this&lt;/a&gt;. &lt;a href=&quot;#fnref:refs&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Wardley maps at the low end</title>
   <link href="http://santtu.iki.fi/2015/09/11/wardley-maps-and-startups"/>
   <updated>2015-09-11T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/09/11/wardley-maps-and-startups</id>
   <content type="html">&lt;p&gt;I have had this nagging thought about &lt;a href=&quot;http://blog.gardeviance.org/2015/02/an-introduction-to-wardley-value-chain.html&quot;&gt;Wardley maps&lt;/a&gt;. Don’t get
me wrong, I love Wardley maps! For example I have found the concept of
evolution to give me insight into a lot of both recent and older
events both generally in the technology sector as well as in business
aspects of companies I have worked for and worked with.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But&lt;/em&gt;: There’s this thing about almost all the practical examples I
have seen on Simon’s blog:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They are examples from large companies and large public organizations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I work mostly with smaller companies — startups. Can Wardley maps be
used with them? Would mapping offer any benefits?&lt;/p&gt;

&lt;p&gt;It is possible to argue both ways — startups are resource constrained
and would greatly benefit from increasing their leverage (more bang
for the buck), yet the same resource constraints may make it difficult
to actually execute strategic manipulation plays! There’s also
tremondous variability between different startups. So,&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Is it possible to use Wardley maps with startups?&lt;/strong&gt; (I think:
Most likely)&lt;/li&gt;
  &lt;li&gt;If so, &lt;strong&gt;are there any benefits of using them?&lt;/strong&gt; (Probably)&lt;/li&gt;
  &lt;li&gt;Finally, &lt;strong&gt;what are those benefits and how are they influenced by
the company size?&lt;/strong&gt;&lt;sup id=&quot;fnref:size&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:size&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (Maybe)&lt;/li&gt;
&lt;/ol&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;img src=&quot;/assets/posts/5541356248_7b62e34976_z.jpg&quot; alt=&quot;Does size matter?&quot; /&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Does size matter? (Source:
&lt;a href=&quot;https://www.flickr.com/photos/miguel77/5541356248/&quot;&gt;Miguel&lt;/a&gt;, CC BY-NC
2.0)&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I am pretty new to using Wardley maps within organizations, so it is
possible that I’m doing everything wrong, or being biased, and
regardless my sample size that I’ve studied with this question in mind
is only three companies so far, and even then the feedback is from
short hands-on introduction sessions to Wardley mapping. These sample
companies were soliticed from my current customers and professional
network and included:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A small team forming a virtual startup within a larger organization,
being responsible for a commercial web-based B2B service recently
introduced to the market.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A medium-sized group at a startup with MVP development in progress
in a healthcare segment. This segment is likely to face disruption
(war!) due to digitization of its services within a few years.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A larger group at a startup in very early forming phase — they have
a business idea but no clarity of a MVP at the time of the session.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;small&gt;So something between a few people to at most about ten people,
okay?  I think it possible to define an early startup’s size only
after the fact when the difference between contributors and
hang-arounds has become clear.&lt;/small&gt;&lt;/p&gt;

&lt;h2 id=&quot;using-wardley-maps&quot;&gt;Using Wardley maps&lt;/h2&gt;

&lt;p&gt;Once you have a Wardley maps of your business and the surrounding
business ecosystem, there are several possibilities on how to use it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.gardeviance.org/2015/05/on-61-different-forms-of-gameplay.html&quot;&gt;Manipulate&lt;/a&gt; the playing field to your own advantage.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.gardeviance.org/2015/05/on-61-different-forms-of-gameplay.html&quot;&gt;Anticipate&lt;/a&gt; developments that will occur and potential
actions by competitors.&lt;/li&gt;
  &lt;li&gt;Decide what to &lt;a href=&quot;http://blog.gardeviance.org/2015/04/experiment-or-plan.html&quot;&gt;purchase or outsource&lt;/a&gt; and what to do internally.&lt;/li&gt;
  &lt;li&gt;Select best &lt;a href=&quot;http://blog.gardeviance.org/2015/04/experiment-or-plan.html&quot;&gt;models&lt;/a&gt; to use for internal work.&lt;/li&gt;
  &lt;li&gt;Choose appropriate &lt;a href=&quot;http://blog.gardeviance.org/2015/04/experiment-or-plan.html&quot;&gt;purchasing models&lt;/a&gt; for external sourcing.&lt;/li&gt;
  &lt;li&gt;Define &lt;a href=&quot;http://blog.gardeviance.org/2015/04/the-only-structure-youll-ever-need.html&quot;&gt;teams&lt;/a&gt;, their goals and responsibilities.&lt;/li&gt;
  &lt;li&gt;Define &lt;a href=&quot;http://blog.gardeviance.org/2015/04/the-only-structure-youll-ever-need.html&quot;&gt;roles and hiring profiles&lt;/a&gt; for different teams.&lt;/li&gt;
&lt;/ol&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/wardley-map-benefits-as-a-wardley-map.svg&quot;&gt;&lt;img src=&quot;/assets/posts/wardley-map-benefits-as-a-wardley-map.svg&quot; alt=&quot;Wardley map benefits&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;What I found out is that in this sample of startups:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Manipulating the playing field was felt to be out of reach and
anticipation of playing field changes and competitor actions were
similarly felt to be “too far out”.&lt;/li&gt;
  &lt;li&gt;Having multiple teams, defining hiring profiles and deciding
internal work model were also mostly out of scope as hiring and
teaming is driven by immediate tactical needs more than any
long-term planning effort&lt;sup id=&quot;fnref:hiring&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:hiring&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. It is pretty pointless trying to
create artificial team divisions among five people or less, or try
to run a single team in different operating modes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However there were things that the audience found useful:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;“Eye-opener” was a frequent comment when talking about “purchase,
outsource or develop internally” decisions.&lt;/li&gt;
  &lt;li&gt;Differences between purchasing models for different evolutionary
stages was also appreciated.&lt;/li&gt;
  &lt;li&gt;Although I suspect the understanding of &lt;em&gt;evolution&lt;/em&gt; was superficial
at this stage, comments were made about how this helped visualize
potential risks of relying too heavily on early stage technologies
(leaning too much on the “bottom left quadrant”).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-to-make-of-this&quot;&gt;What to make of this?&lt;/h2&gt;

&lt;p&gt;Although it is nice to have provided useful insights to participants
in these sessions, the relevant question really is &lt;strong&gt;did this offer
more value than using the same time on some other strategic method&lt;/strong&gt;
(self-study or facilitated)?&lt;/p&gt;

&lt;p&gt;Answer: Yes and no and it depends.&lt;sup id=&quot;fnref:answer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:answer&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Yes, it clearly provided insights for people on topics they might
have come across only by chance.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;No, as these insights were &lt;strong&gt;common knowledge&lt;/strong&gt;. Different project,
development and organizational models are nothing new and neither is
the knowledge that there’s no one-size-fits-all method.&lt;sup id=&quot;fnref:pundits&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:pundits&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;
The same situation is with outsourcing methods — hey, this stuff is
introductory business course material.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It depends — I have found out that a consultant, a facilitator or a
teacher often is paraphrasing common information that the audience
&lt;strong&gt;already knows&lt;/strong&gt; but has &lt;strong&gt;not yet understood&lt;/strong&gt;. Helping with this
step between knowledge and understanding can be valuable in itself.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;!-- &gt; Given a small random sample from a population of competent people --&gt;
&lt;!-- &gt; (people ending up in an early-stage startup) there are bound to be --&gt;
&lt;!-- &gt; gaps in knowledge and skills. Through a sort of reverse causality --&gt;
&lt;!-- &gt; companies that are funded early are more likely to have been founded --&gt;
&lt;!-- &gt; by experienced enterpreneurs with existing connections to --&gt;
&lt;!-- &gt; funders. So they have both resources and experience already packed --&gt;
&lt;!-- &gt; in. Conversely companies that are not well funded early (thus --&gt;
&lt;!-- &gt; lacking in resources) are more likely to have young (less --&gt;
&lt;!-- &gt; experienced) founders thus suffering a double whammy regarding --&gt;
&lt;!-- &gt; strategic capability. --&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Based on feedback and my own observations from these relatively short
introductory sessions with early-phase startups, I would say the
benefit of using Wardley maps for small, early-phase startups is
inconclusive.&lt;/p&gt;

&lt;p&gt;There are clearly some benefits, but these benefits might not be
attributable to Wardley maps specifically. There is a possibility
these benefits could have been reached with some other method too with
comparable effort. Even then the benefits appear to be more tactical
than strategic.&lt;/p&gt;

&lt;h2 id=&quot;afterthought&quot;&gt;Afterthought&lt;/h2&gt;

&lt;p&gt;Well… there is definitely a possibility for early-phase startups with
little resources, with enough drive and willpower, to manipulate the
strategic playing field to their advantage. For most? Probably not.&lt;/p&gt;

&lt;p&gt;After some contemplation I thought of one situation where Wardley maps
&lt;em&gt;might&lt;/em&gt; prove very useful for early-phase startups: when it is looking
for funding. Putting effort into using Wardley maps and understanding
the strategic business environment, at least I believe so, would help
a company put forward a much better story about the company and its
business for potential investors.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I think the case for “strategy” in startups faces the same problem
as any “X” that could help them plan and execute better: there are
too many “X”s, too little time and not enough money and time to
throw around. It just is not feasible to evaluate and use every “X”
that &lt;em&gt;might or might not work&lt;/em&gt;.  I think that founders who realize
their need to understand the strategic playing field and the will to
manipulate it are already in the “better off” category — they
probably are more experienced with better connections and better
access to funding, too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For a next step, how about looking into still-quite-early startups with seed
funding, and an MVP on the market?&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:size&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Here I am using “company size” as a proxy for its resources. This is just a heuristic, as said, there’s tremondous variability between startups. &lt;a href=&quot;#fnref:size&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:hiring&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There is of course a lot of effort put into hiring “the right people”. This hiring just is not driven by any understanding of bimodal- or trimodal IT. &lt;a href=&quot;#fnref:hiring&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:answer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;My favourite answer to all yes-no questions. &lt;a href=&quot;#fnref:answer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:pundits&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Most people I know and value have no illusion that any variant of agile, lean or six sigma would be a fit for all needs. This view is supported by plenty of research too. &lt;a href=&quot;#fnref:pundits&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Watts, watts, watts!</title>
   <link href="http://santtu.iki.fi/2015/06/18/browser-power-consumption"/>
   <updated>2015-06-18T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/06/18/browser-power-consumption</id>
   <content type="html">&lt;p&gt;A few days ago I read this tweet from Nicholas Weaver about laptop
fans spinning on a certain web site.&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;blockquote class=&quot;twitter-tweet tw-align-center&quot; lang=&quot;en&quot;&gt;
  &lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/ncweaver&quot;&gt;@ncweaver&lt;/a&gt; &lt;a href=&quot;https://twitter.com/mikko&quot;&gt;@mikko&lt;/a&gt; How about energy labels for websites? Forbes clearly a D.&lt;/p&gt;
  &lt;p&gt;— Santeri Paavolainen (@paavolainen) &lt;a href=&quot;https://twitter.com/paavolainen/status/610782782965555200&quot;&gt;June 16, 2015&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It was sort of a joke. Think
&lt;a href=&quot;https://en.wikipedia.org/?title=European_Union_energy_label&quot;&gt;European Union energy labeling&lt;/a&gt;. Would
a random site get an A++ or a D energy efficiency label? Based on
what? What a thought!&lt;/p&gt;

&lt;p&gt;But as things go, that thought would not leave me alone. There
&lt;strong&gt;clearly&lt;/strong&gt; are some applications that routinely will busyloop on a
cpu core&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. As Nicholas said, there are also some web sites that put
a large burden on the processor, too. You can literally feel that as
&lt;a href=&quot;https://en.wikipedia.org/wiki/Laptop_cooler&quot;&gt;&lt;strong&gt;heat on your lap&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-much&quot;&gt;How much?&lt;/h2&gt;

&lt;p&gt;The question is &lt;strong&gt;how much power can a power-hungry website consume?&lt;/strong&gt;&lt;/p&gt;

&lt;div style=&quot;text-align: center; padding: 1em; line-height: 1.2em; font-size: x-large;&quot;&gt;
  &lt;p&gt;I am ready. I have a pluggable power meter, computer, paper and
a pen.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;So I set up to work. First I measured&lt;sup id=&quot;fnref:methods&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:methods&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; some baseline power usage levels
on my laptop&lt;sup id=&quot;fnref:laptop&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:laptop&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; with different screen brightness levels:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/website-power-baseline.svg&quot;&gt;&lt;img src=&quot;/assets/posts/website-power-baseline.svg&quot; alt=&quot;baseline power usage graphs&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;figcaption&gt;
    &lt;p&gt;From left to right: lowest visible brightness level, screen off, 50% brightness, 50% brightness with browser running and 100% screen brightness.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I decided to use 50% screen brightness for my tests. Notice that the
difference between screen off and lowest brightness level seems
neglible, which is interesting. I had expected that the backlight
would consume significantly more power than screen completely
off. (The measurement baseline of screen at 50% intensity with Google
Chrome running and a single incognito window open used 10.8 ± 0.7 W.)&lt;/p&gt;

&lt;p&gt;Having set up the baseline, time to browse some sites! After gathering
data on several randomly chosen sites I divided sites into three
groups, &lt;strong&gt;low&lt;/strong&gt;, &lt;strong&gt;medium&lt;/strong&gt; and &lt;strong&gt;high&lt;/strong&gt; power usage:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/website-power-measurements.svg&quot;&gt;&lt;img src=&quot;/assets/posts/website-power-measurements.svg&quot; alt=&quot;power usage graphs&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;figcaption&gt;
    &lt;p&gt;From left to right, in low power group: &lt;a href=&quot;http://www.newscientist.com&quot;&gt;New Scientist&lt;/a&gt;, &lt;a href=&quot;http://www.bbc.com&quot;&gt;BBC&lt;/a&gt;, &lt;a href=&quot;http://www.apple.com&quot;&gt;Apple&lt;/a&gt;, &lt;a href=&quot;http://www.youtube.com&quot;&gt;YouTube&lt;/a&gt;, &lt;a href=&quot;http://www.google.com&quot;&gt;Google&lt;/a&gt;; in medium power group: &lt;a href=&quot;http://vimeo.com&quot;&gt;Vimeo&lt;/a&gt; playing a video, YouTube video in fullscreen mode, Vimeo video in fullscreen mode, &lt;a href=&quot;http://www.theguardian.com&quot;&gt;The Guardian&lt;/a&gt;, YouTube video; in high power group: &lt;a href=&quot;http://www.nytimes.com&quot;&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Power usage by group was&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Low power group: 10.7 ± 0.9 W&lt;/li&gt;
  &lt;li&gt;Medium power group: 20 ± 3 W&lt;/li&gt;
  &lt;li&gt;High power group: 48 ± 3 W&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considering Nicholas’s comment I was surprised about Forbes being in
the low power group. One factor might have been that I have the Flash
plugin disabled by default, and there was at least one Flash ad on the
Forbes front page. Secondly, I was expecting a more uniform power use
distribution, but at least these results were quite stratified. I was
also expecting that video sites would be the most power hungry. They
weren’t.&lt;/p&gt;

&lt;p&gt;The main conclusion based on this very limited sampling is nonetheless
clear: &lt;strong&gt;there are significant differences in browser power use
between web sites&lt;/strong&gt;. The difference between low and medium group is
almost 10 watts and grows to &lt;strong&gt;almost 50 watts&lt;/strong&gt; between low power
group and The New York Times site.&lt;/p&gt;

&lt;h2 id=&quot;post-scriptum-does-that-matter&quot;&gt;Post Scriptum: Does that matter?&lt;/h2&gt;

&lt;p&gt;The global electricity consumption&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; is about 2 &lt;strong&gt;terawatts&lt;/strong&gt;. Even
if we assume that &lt;strong&gt;30% of world population use 1 hour a day browsing
the web&lt;/strong&gt; then 10 watts more power would mean a total of 875 megawatts
more power consumed, which is only 440 parts per million of the global
electricity consumption.&lt;/p&gt;

&lt;p&gt;So is 875 MW a large number or not? Perhaps it is better to compare it
against &lt;strong&gt;power conservation efforts&lt;/strong&gt;. Let’s take the European Union
energy labels for refridgerators as a reference. When the labels were
introduced the lowest energy label was an A. Now it is A+++ whose
difference is 33 kWh per annum&lt;sup id=&quot;fnref:5&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. This difference multiplied by the
number of households in EU-28&lt;sup id=&quot;fnref:6&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; totals up to 790 megawatts.&lt;/p&gt;

&lt;p&gt;In the same ballpark.&lt;/p&gt;

&lt;p&gt;These are just numbers, but I think they show that it is possible that
power-hungry websites can potentially consume significant amount of
power by end-user computers.&lt;/p&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m not naming any birds, thundering or not. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:methods&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Most applications turned off, no Time Machine backups running, battery at 100%, not using the computer during measurements, starting measurements only 10-30 seconds after page load, pausing video until player has cached as much as possible before video plays, measuring power meter visually from a digital display at 5 second intervals for 30 seconds for a total of 7 measurements for each test. &lt;a href=&quot;#fnref:methods&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:laptop&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;13” Retina Macbook Pro, 2013 model. &lt;a href=&quot;#fnref:laptop&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/Electric_energy_consumption#Electricity_Consumption_and_GDP&quot;&gt;Wikipedia&lt;/a&gt; &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is actually normalized to the volume of the refridgerator, but I’m willing to take a chance in taking this difference as a valid average. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;210 million, source: &lt;a href=&quot;http://ec.europa.eu/eurostat/statistics-explained/index.php/Household_composition_statistics&quot;&gt;Eurostat&lt;/a&gt; &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Custom Termination Policy for Auto Scaling</title>
   <link href="http://santtu.iki.fi/2015/04/25/custom-termination-policy"/>
   <updated>2015-04-25T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/04/25/custom-termination-policy</id>
   <content type="html">&lt;p&gt;While chatting with &lt;a href=&quot;https://twitter.com/avasol&quot;&gt;Thomas Avasol&lt;/a&gt; about
auto scaling group termination policies&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I got an idea on how to
implement custom termination policies for AWS auto scaling groups.&lt;/p&gt;

&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;

&lt;p&gt;(Feel free to skip ahead if you are familiar with auto scaling groups
and termination policies.)&lt;/p&gt;

&lt;p&gt;A bit of a background first: When an auto scaling group is scaled
&lt;em&gt;down&lt;/em&gt;, an instance to be terminated needs to be picked. There are
sevaral policies to choose from: oldest/newest instance, oldest launch
configuration, closest to full instance hour and the default (most
complex) one. A customer gets to choose one of these and &lt;em&gt;that’s
it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If none of these suited you, there are some optios available:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Use termination protection to prevent some instances being picked up
for down-scaling termination. (This has been recommended to me as
one way by several AWS engineers.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run your own down-scale scheduler in an instance. This would
effectively implement the downscaling logic itself, but with your
own custom twist for choosing instances to terminate.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I consider the first one almost a kludge — an it’s a binary decider,
so more nuanced policies are impossible with it anyway — while the
second one has superb flexibility, it brings in a new potential SPOF
and maintenance burden. So neither is a perfect solution.&lt;/p&gt;

&lt;p&gt;Oh, and &lt;strong&gt;why&lt;/strong&gt; would you want a custom termination policy? Well…
maybe those instances host large caches, and you’d like to terminate
instances with the least filled caches? Or you are running batch jobs
from a queue, where some jobs run long and some short and when jobs
are drained you’d want terminate only instances without jobs?&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(You could run the downscale scheduler inside the auto scale
group, but that forces you to open the can of distributed worms
including leader worm election and all that. I would not want to go
down that road. It is much easier to instead run the scheduler in an
instance within an auto scale group set to one instance in size,
ensuring it’ll get re-created. Either way, it requires an instance, a
thing that I’d like to avoid for smaller groups and simpler custom
termination policies.)&lt;/small&gt;&lt;/p&gt;

&lt;h2 id=&quot;idea-&quot;&gt;Idea 💡&lt;/h2&gt;

&lt;p&gt;Downscaling in an auto scaling group works when a CloudWatch alarm is
triggered, which in turn is set to trigger an scaling action that then
changes the desired instance count.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Now… alarms can also send notifications to SNS topics,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SNS topics can trigger Lambda functions,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Lambda functions can be assigned IAM roles, and Lambda functions
can access all AWS API functionality that the IAM role allows,&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Ergo&lt;/strong&gt;, I can move the custom termination policy code to a Lambda
function without needing to run a separate instance.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With my head humming I started hacking at it and got a
proof-of-concept version running already a few hours later.
&lt;strong&gt;It &lt;strike&gt;is alive&lt;/strike&gt; works!&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;

&lt;p&gt;I’ll tell you how to actually set up this in a while, but first,
here’s the Lambda code.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/santtu/7e759d30f11dca78e3cf.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;It’s a bit verbose. Using Underscore or Coffeescript surely would be
more readable and/or compact. I’m not really a Node.js developer which
probably also shows. This certainly is &lt;strong&gt;not production quality&lt;/strong&gt; as
it makes quite a bit of assumptions and has hard-coded values in
it. &lt;em&gt;This is a proof-of-concept code!  Caveat emptor!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code is straightforward: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exports.handler&lt;/code&gt; will get called, it’ll
extract auto scale group name from the SNS notification, then iterate
over running instances in the group and fetch a &lt;em&gt;total time&lt;/em&gt; value via
HTTP from these instances (a custom CloudWatch metric would do as
well), finally picking the instance with the lowest &lt;em&gt;total time&lt;/em&gt;
value.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;The Lambda function above will not in itself yet do anything. To run
it, you need to first (assuming you already have auto scale group set
up):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create IAM role with enough permissions to do auto scaling actions&lt;/li&gt;
  &lt;li&gt;Create the Lambda function&lt;/li&gt;
  &lt;li&gt;Create an SNS topic and add a subscription for it to call the Lambda
function&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create CloudWatch alarms to send a notification to the SNS topic
from above when you want a downscale to occur.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;You will need multiple alarms set up&lt;/strong&gt; for multiples of your
cooldown period. For example, if you want to downscale if average
CPU load is less than 25% for 10 minutes, you’ll have to set up the
first alarm at 10 minutes, second one at 20 minutes, third at 30
minutes up to the maximum number of your scaling group (see below
for details why).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Done!&lt;/p&gt;

&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;/h2&gt;

&lt;p&gt;I ran into some limitations of Lambda and CloudWatch when working on
this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Lambda functions can access instances only via public IP addresses —
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PrivateIpAddress&lt;/code&gt; does not work. This is a bit of a security
bother, so I’d actually suggest to push custom cloudwatch metrics
from instances that the code would read without relying on public
access.&lt;/p&gt;

    &lt;p&gt;(I’d like to refer to Lambda functions in security groups directly
and use internal IP addresses to access AWS resources.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I originally had the downscale handler set the triggering cloudwatch
alarm to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSUFFICIENT_DATA&lt;/code&gt; state in a hope to make it re-trigger
later again. It got stuck in a re-trigger race loop, getting
repeatedly triggered (downscaling the group into 1 instance in one
fell swoop).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I could not figure out a way within AWS services to cause a delay in
re-triggering the downscale handler. It is possible to have delay
queues in SQS, but no way to trigger Lambda functions based on SQS
messages. If there ever is a way to trigger Lambda functions from
SQS messages (or route SQS messages to a SNS topic) then it would be
possible for the handler to inspect the original alarm state after a
cooldown period and requiring only a single alarm.&lt;/p&gt;

    &lt;p&gt;(I’d like either a way to schedule Lambda call for later, to trigger
Lambda functions via an SQS delay queue, or to specify to an alarm
to retrigger after some cooldown delay if it is still in a trigger
state.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://aws.amazon.com/lambda/&quot;&gt;Lambda&lt;/a&gt; is currently available only
in US East, US West (Oregon) and EU West regions, which may limit
its usefulness at the moment. On the other hand, it should become
available in other regions soon-ish.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that auto scaling apparently has some internal logic that causes
it to inspect the alarm state after cooldown period, retriggering the
scaling action multiple times as needed. An alarm, however, will send
only a single notification to SNS topic, thus making the Lambda
function edge-triggered on the alarm. (Auto scaling magic turns that
into level-triggered action instead.)&lt;/p&gt;

&lt;p&gt;Anyway that’s it — please drop a comment below if you find this
useful!&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;On 21st April 2015 at AWS Summit Stockholm, to be precise. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Picoservice bruhahaha</title>
   <link href="http://santtu.iki.fi/2015/04/21/picoservice-bruhahaha"/>
   <updated>2015-04-21T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/04/21/picoservice-bruhahaha</id>
   <content type="html">&lt;p&gt;I’ve been busy, as again, an haven’t had a good chance to continue on
my &lt;a href=&quot;/tags.html#µ²services-ref&quot;&gt;µ²services&lt;/a&gt; series. I’m planning to
discuss more of the potential implications of technology development
meeting microservice architecture models. But this post isn’t about
that.&lt;/p&gt;

&lt;p&gt;Instead I want to comment a bit on the nano/picoservice commentary
found over the net. For example:&lt;/p&gt;

&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;!-- &lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p&gt;Picoservices. Like &amp;quot;hello, world&amp;quot;.&lt;/p&gt;&amp;mdash; MY Camelopardalis (@pavlobaron) &lt;a href=&quot;https://twitter.com/pavlobaron/status/567393808690581506&quot;&gt;February 16, 2015&lt;/a&gt; --&gt;
&lt;!-- &lt;/blockquote&gt; --&gt;

&lt;blockquote class=&quot;twitter-tweet tw-align-center&quot; lang=&quot;en&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;https://twitter.com/michaelneale&quot;&gt;@michaelneale&lt;/a&gt; I thought we agreed that was the hip new marketing term for functions?&lt;/p&gt;
  &lt;p&gt;— Mark Wotton (@mwotton) &lt;a href=&quot;https://twitter.com/mwotton/status/562424720490901504&quot;&gt;February 3, 2015&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!-- &lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p&gt;So we&amp;#39;ve got services and microservices. Can we get a nanoservice? picoservice? femtoservice?&lt;/p&gt;&amp;mdash; Snark As a Service (@petrillic) &lt;a href=&quot;https://twitter.com/petrillic/status/574972031470432256&quot;&gt;March 9, 2015&lt;/a&gt; --&gt;
&lt;!-- &lt;/blockquote&gt; --&gt;

&lt;!-- &lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p&gt;&amp;quot;MICROSERVICES ARE TOO MONOLITHIC. LEVERAGE OUR NANOSERVICE FOR MOST IMPORTANT COMMUNICATIONS IN ROBUST CLOUD.&amp;quot; &lt;a href=&quot;http://t.co/7hLpkq3FMY&quot;&gt;http://t.co/7hLpkq3FMY&lt;/a&gt;&lt;/p&gt;&amp;mdash; Taylor Edmiston (@kicksopenminds) &lt;a href=&quot;https://twitter.com/kicksopenminds/status/573552541394403329&quot;&gt;March 5, 2015&lt;/a&gt; --&gt;
&lt;!-- &lt;/blockquote&gt; --&gt;

&lt;p&gt;&lt;strong&gt;I absolutely love these comments!!&lt;/strong&gt; I absolutely think that at
least 95% of use of “microservice” is just hot air. However if you
take “microsizing” as an end goal itself and extrapolate to smaller
and smaller scales you get nanoservices and picoservices on an
function and instruction level granularity:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet tw-align-center&quot; lang=&quot;en&quot;&gt;
  &lt;p&gt;1k smaller microservice is nanoservice; exposes assembly instructions via HTTP+JSON; pikoservices become inadressable due to quantum effects&lt;/p&gt;
  &lt;p&gt;— Tomas Petricek (@tomaspetricek) &lt;a href=&quot;https://twitter.com/tomaspetricek/status/540159905236520960&quot;&gt;December 3, 2014&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tomas of course is making a point of this absurdity.&lt;/p&gt;

&lt;p&gt;What I think what microservices (and by extension, nano and pico too)
are: &lt;strong&gt;Microservices are externally loosely coupled but internally
tightly coupled functional service components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Although it is not evident from this definition, most value from
microservice architecture actually comes from &lt;strong&gt;organizational
improvement&lt;/strong&gt; by making the underlying loose-tight coupling &lt;strong&gt;explicit
in development, management and operations&lt;/strong&gt;. This also means that the
true potential value of a microservice architecture is difficult to
determine as it is more dependent on the development organization
itself than in the actual software they are developing.&lt;/p&gt;

&lt;p&gt;In the end you must ask yourself&lt;/p&gt;

&lt;div style=&quot;text-align: center; padding: 1em; line-height: 1.2em; font-size: x-large;&quot;&gt;
  &lt;p&gt;Do microservices make &lt;strong&gt;snarzzz&lt;/strong&gt; more &lt;span style=&quot;white-space: nowrap;&quot;&gt;&lt;strong&gt;flordbious&lt;/strong&gt;?&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;It just depends.&lt;/strong&gt; Depends on you, your team, your resources, your
processes, your choice of technology, everything. Investigate and
decide yourself. Don’t be a slave to
&lt;a href=&quot;http://www.slideshare.net/swardley/playing-chess-with-companies/15&quot;&gt;backward causality&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So to clarify for my imaginary pundit what &lt;strong&gt;I&lt;/strong&gt; mean and don’t mean
when talking about micro- or µ²services:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Replacing function calls with “services” is just
&lt;strong&gt;idiotic&lt;/strong&gt;. Plainly and simply idiotic and anyone who claims anything
remotely similar is a plain walking and talking bullshit machine.&lt;/p&gt;

    &lt;p&gt;This same thought experiment was done in reality with remote
procedure calls (RPC) already a decade ago and the result is &lt;strong&gt;local
and remote operations are fundamentally different&lt;/strong&gt;. You can not
create a distributed system based on “function invocation” pattern.&lt;/p&gt;

    &lt;p&gt;A call to a library routine should now and in the future be a local
function call&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I use or at least used to use the term µ²services to emphasise that
the trend of shrinking containers may have (some unforeseen)
consequences on how we develop and use microservices.&lt;/p&gt;

    &lt;p&gt;Perhaps I should just stop using that term instead.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, check out some of these cool posts and sites:
&lt;a href=&quot;http://www.skjegstad.com/blog/2015/03/25/mirageos-vm-per-url-experiment/&quot;&gt;A VM for every URL&lt;/a&gt;
by Magnus Skjegstad,
&lt;a href=&quot;https://taidevcouk.wordpress.com/2015/02/08/microservice-maturityclassification-model-proposal-first-draft/&quot;&gt;Microservice Classification Model Proposal&lt;/a&gt;
by Daniel Bryant and of course, the
&lt;a href=&quot;http://shoutcloud.io/&quot;&gt;ALL CAPS AS A SERVICE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;P.S. All of the tweets above were written clearly with tongue in
cheek. Yet, the fact that people are feeling the need to dismiss
“picoservices” for me is a sign that the idea of shrinking services as
a goal itself is floating around — and since I’ve been writing about
&lt;a href=&quot;/tags.html#µ²services-ref&quot;&gt;µ²services&lt;/a&gt; I want to make it clear that
&lt;em&gt;that particular&lt;/em&gt; model of sub-microservices is not what I am talking
about.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Substitute your own corporate, process or agile buzzwords. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;With no significant external constraints or requirements applying. This is not science, this is engineering. You can always find counter-examples but they do not a general case make. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Divine concurrency</title>
   <link href="http://santtu.iki.fi/2015/02/14/concurrency-and-uuservices"/>
   <updated>2015-02-14T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/02/14/concurrency-and-uuservices</id>
   <content type="html">&lt;p&gt;In &lt;a href=&quot;/2015/01/31/path-ahead-uuservices&quot;&gt;previous post&lt;/a&gt; I
described µ²services, a system development model that is based on
extrapolation of current trends in microservices and shrinking
containers. I argumented that potential benefits of µ²service model
&lt;em&gt;might&lt;/em&gt; outweigh its costs. But are µ²services really technically
feasible?&lt;/p&gt;

&lt;p&gt;In this and future posts I’ll go through some of technical details
both from feasibility and benefit points of view, with probably one
idea per blog post to keep them manageable in size.&lt;/p&gt;

&lt;p&gt;To summarize &lt;a href=&quot;/2015/01/31/path-ahead-uuservices&quot;&gt;µ²services&lt;/a&gt;: µ²services is container-per-request model where a new
virtual machine&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is created for
&lt;strong&gt;each request&lt;/strong&gt; made to the service which then handles the request
&lt;strong&gt;and only that request&lt;/strong&gt; and is destroyed after response is
generated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A warning for the reader:&lt;/strong&gt; All of this is pure speculation on my
part. µ²services might happen, but they might not. This is
futurology. &lt;strong&gt;Do not think this is technology that currently exists&lt;/strong&gt;
(although technological precursors exist.)&lt;/p&gt;

&lt;h2 id=&quot;divine-concurrency&quot;&gt;&lt;a name=&quot;concurrency&quot;&gt;&lt;/a&gt;Divine concurrency&lt;/h2&gt;

&lt;p&gt;I have previously argued that &lt;a href=&quot;/2014/03/06/network-and-parallelism-in-erlang#concurrency&quot;&gt;concurrency is hard&lt;/a&gt; and developers should primarily use language and software architecture constructs that naturally result in &lt;em&gt;safe code&lt;/em&gt;. I think µ²services offer a way to create &lt;strong&gt;massively parallel&lt;/strong&gt; service architectures where risks associated with concurrency (dead- and livelocks, mutable data and so on) are either completely eliminated or largely reduced and limited in scope.&lt;/p&gt;

&lt;p&gt;The graph below shows a hypotethical call dependency path for a
request. The service is composited of multiple smaller (micro)services
which themselves are a group of µ²services. State is managed
separately and the state storage mechanism is shared by all of these
components (via a deployment configuration parameter). The graph could
describe a conventional service as well where the colored blobs would
signify a service process boundary and circles functional elements
within the service.&lt;/p&gt;

&lt;figure&gt;

  &lt;p&gt;&lt;a href=&quot;/assets/posts/uuservices-flow.png&quot;&gt;&lt;img src=&quot;/assets/posts/uuservices-flow.png&quot; alt=&quot;Call graph of a request to µ²service&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;µ²services responding to a request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/listings&lt;/code&gt; — so
far this looks like a regular microservice.. (Letters and numbers
match those in the second graph.)&lt;/p&gt;

  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;In an µ²service the colored blobs are &lt;strong&gt;service&lt;/strong&gt; boundaries, a
mechanism to group several different µ²service endpoints
together. Perhaps they all share the same configuration elements, or
same repository and release tag or similar. With µ²services a
“service” is more of a convention than a fixed entity.&lt;/p&gt;

&lt;p&gt;Individual circles represent separate µ²service endpoints, pieces of
code that can be invoked externally by either users or other
µ²services. When not running these are essentially &lt;strong&gt;templates&lt;/strong&gt; that
are instatiated when a request is received. Thus each inbound arrow in
the call graph represents a &lt;strong&gt;new virtual machine&lt;/strong&gt; that starts to run
the &lt;strong&gt;service code&lt;/strong&gt;. For example, calls &lt;em&gt;c&lt;/em&gt; and &lt;em&gt;f&lt;/em&gt; run the same
function&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; but in &lt;em&gt;different&lt;/em&gt; virtual machines. Same applies for &lt;em&gt;n&lt;/em&gt;
and &lt;em&gt;o&lt;/em&gt; which result in &lt;em&gt;different&lt;/em&gt; virtual machines 13 and 15.&lt;/p&gt;

&lt;p&gt;As described, all µ²service call graphs are acyclic — while calls “up
the chain” are logically possible, they result in separate instances
making the physical call graph acyclic. The graph below is another
view of the same call graph, but structured to make it clear that
there exist only forward dependencies. It shows the lifetime of each
call (virtual machine), where each either creating a new virtual
machine (request) or resulting in a termination of one
(response).&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/uuservices-vms.png&quot;&gt;&lt;img src=&quot;/assets/posts/uuservices-vms.png&quot; alt=&quot;Virtual machine invocations and terminations on a request to µ²service&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Virtual machines running concurrently when processing the
request in the earlier graph.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Concurrency is &lt;strong&gt;difficult&lt;/strong&gt; in monolithic services. A single spinning
thread can block the whole system. Microservices offer a potential for
increased concurrency by
&lt;a href=&quot;http://techblog.netflix.com/2013/02/rxjava-netflix-api.html&quot;&gt;allowing concurrent requests to dependent services&lt;/a&gt;. µ²services
with even finer service decomposition has the potential to offer even
more concurrency.&lt;/p&gt;

&lt;p&gt;Note also that since each service-to-service request is explicit they
can be separately
&lt;a href=&quot;https://github.com/Netflix/Hystrix&quot;&gt;managed for failures and timeouts&lt;/a&gt;. Timed
out requests are no longer left running — terminated requests will
result in termination of their container, which will propagate request
terminations further down the chain. For example in the graph above if
the user terminated the request (closing the HTTP connection), it
would cause instance 1 to terminate, followed recursively by all
dependent instances. This would occur even if some code was stuck in
an infinite loop&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;!&lt;/p&gt;

&lt;p&gt;Like all things, µ²service model is not a magic dust that could turn any
system into massively parallel system. It is not, and cannot be. What
it can do is what &lt;a href=&quot;/2014/03/06/network-and-parallelism-in-erlang#concurrency&quot;&gt;Erlang as a language&lt;/a&gt; has done —
it can make concurrent programming a little less error-prone. One benefit — compared to Erlang at least: using a different service &lt;strong&gt;model&lt;/strong&gt; does not require you to learn a new programming &lt;strong&gt;language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;That’s all this time. I would appreciate any comments on uuservices —
 please share your thoughts by adding a comment below. Thanks.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’m using “virtual machine” to emphasise the isolation between µ²services. Zones, containers, schmontainers, whatever… as long as all service calls are both spatially and temporally isolated. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;With &lt;strong&gt;function&lt;/strong&gt; I primarily emphasise µ²service’s difference to traditional monolithic services or even microservices. &lt;strong&gt;µ²service functions&lt;/strong&gt; are not &lt;strong&gt;programming language&lt;/strong&gt; functions — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;image.flip()&lt;/code&gt; is a local function call that occurs within the runtime environment of the µ²service instance. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Here’s a question on your favourite web service framework: If you make a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET&lt;/code&gt; request handler that will sleep for a minute and make a request to it killing the client &lt;strong&gt;immediately&lt;/strong&gt; after request has been sent. &lt;strong&gt;When will the request handler terminate?&lt;/strong&gt; Immediately on receiving TCP FIN? After the sleep completes? Somewhere in between? &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>µ²services</title>
   <link href="http://santtu.iki.fi/2015/01/31/path-ahead-uuservices"/>
   <updated>2015-01-31T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/01/31/path-ahead-uuservices</id>
   <content type="html">&lt;p&gt;Previously I started &lt;a href=&quot;/2015/01/06/trans-earth-protocols&quot;&gt;playing the futurician&lt;/a&gt;, a path I’m now continuing against all good advice. I’ve always envied “visionaries” at companies as they get to play around without any kind of responsibility (they will have long since flocked elsewhere when their predictions can be checked). Similarly I am planning to make bold predictions of a future so far away that a claim of flying pigs would have equal credibility.&lt;/p&gt;

&lt;h2 id=&quot;state-of-the-art&quot;&gt;State of the art&lt;/h2&gt;

&lt;p&gt;Unless you’ve lived under a rock, you must have heard of
&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; (and its take by
&lt;a href=&quot;http://aws.amazon.com/ecs/&quot;&gt;AWS&lt;/a&gt;,
&lt;a href=&quot;https://cloud.google.com/compute/docs/containers&quot;&gt;Google&lt;/a&gt; and
&lt;a href=&quot;http://news.microsoft.com/2014/10/15/dockerpr/&quot;&gt;Azure&lt;/a&gt;), a kind of
applications-on-(almost-)virtual-machines containerization mechanism.&lt;/p&gt;

&lt;p&gt;Yet docker is just one evolutionary step in a long path of application
deployment models. Way way back during pre-history computers were
expensive and &lt;em&gt;so&lt;/em&gt; much slower that CPU cycles were &lt;em&gt;soooo&lt;/em&gt; expensive
it made sense to cram as much services into a single server to
minimize operating and capital costs. This was the era of mainframes,
followed by minicomputers and later UNIX servers as relative hardware
costs kept decreasing. Although the per-cycle cost decreased, for a
very long time the tendency to run multiple services in a single
server remained.&lt;/p&gt;

&lt;p&gt;The widespread rollout of first server virtualization, then of “The
Cloud”, allowed large servers to be splitted into smaller, discrete
virtual machines. This made it feasible and later commonplace to run
only a single service per virtual machine. This step is also crucial
for later adoption of deployment automation as it allows each service
to be equated with a machine, vastly simplifying problem resolution —
there is no fear of hurting “other” services when rebooting (or
re-creating) a one-service machine.&lt;/p&gt;

&lt;p&gt;Docker is one step in this path of shrinking (relative) deployment
footprints. &lt;strong&gt;Fundamentally&lt;/strong&gt; it does not differ from a
service-per-machine model as its containers have in practice similar
isolation properties as earlier service-per-virtual-server model. &lt;strong&gt;In
practice&lt;/strong&gt; it is a major step: Virtual machine startup latency is
anything from half a minute up while a docker container the startup
time is in seconds to tens of seconds range. Other overheads such as
memory and disk use are also reduced — for a single server these
latencies and overheads would not matter much, but in the scope of
cloud services with thousands of servers these seconds and gigabytes
start to add up.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/mainframe-to-cloud.png&quot;&gt;&lt;img src=&quot;/assets/posts/mainframe-to-cloud.png&quot; alt=&quot;Service deployment and cost development&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Service deployment speed has increased while the cost to
run a service has simultanously decreased. (Images courtesy of &lt;a href=&quot;http://commons.wikimedia.org/wiki/Main_Page&quot;&gt;Wikimedia
Commons&lt;/a&gt; and
&lt;a href=&quot;https://www.flickr.com/photos/osde-info/7948643886/in/photostream/&quot;&gt;Clive
Darra&lt;/a&gt;.)&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Coincident to this evolution — or perhaps co-evolved — are
&lt;a href=&quot;http://www.infoq.com/interviews/adrian-cockcroft-microservices-devops&quot;&gt;microservices&lt;/a&gt;. Microservices
in their core are &lt;em&gt;services&lt;/em&gt;, but scaled down so that a single service
performs only narrowly defined operations. User-visible services are
in not monolithic services, but are created as a composite of multiple
microservices orchestrated together. For example see
&lt;a href=&quot;http://techblog.netflix.com/2012/06/netflix-operations-part-i-going.html&quot;&gt;netflix blog&lt;/a&gt;
for discussion on how their business runs hundreds of services on
thousands of machines. This development mirrors the
service-in-a-machine trend by shrinking &lt;em&gt;services&lt;/em&gt; providing further
benefits for simplifying and speeding up deployments.&lt;/p&gt;

&lt;p&gt;So, that’s the situation &lt;em&gt;now&lt;/em&gt;. There is an architectural trend
towards distributed, asynchronous, microservice-based
systems. Simultaneously the environments these services are deployed
into are becoming both more numerous, smaller in footprint, easier to
automate and faster to deploy to.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Here’s a mind-bender for you. Ever heard of &lt;strong&gt;Erlang on Xen&lt;/strong&gt;? Here’s
a &lt;a href=&quot;http://erlangonxen.org/test/latency&quot;&gt;quote&lt;/a&gt; of what it can do:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“On average, only &lt;strong&gt;49ms&lt;/strong&gt; passes between two moments when the Ling
guest kernel is entered and the first Erlang instruction is executed
by the virtual machine.” (emphasis added)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now …&lt;/p&gt;

&lt;div style=&quot;margin: 3em 0; text-align: center; font-size: 200%; color:#ddd;&quot;&gt;
  &lt;p&gt;&amp;lt;your thoughts here&amp;gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;… your eyes skimming to this line took more than those 50
milliseconds. That is &lt;strong&gt;human-scale fast&lt;/strong&gt;. Fast enough a human
pushing a button would no longer detect if each button push was
handled by a separately started Ling instance.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Where is this trend taking us?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Towards more fine-grained service decomposition, and&lt;/li&gt;
  &lt;li&gt;Smaller and simpler containers for services to run in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are of course plenty of caveats. You can only go so far in
decomposition and reductionism. There’s some lower limit for container
size. They don’t matter overall — at least as arguments go — as we can
use extrapolation from these to catch a a glimpse of a future — the
future of &lt;strong&gt;µ²services&lt;/strong&gt; — microservices to the second power.&lt;/p&gt;

&lt;h2 id=&quot;µservices&quot;&gt;µ²services&lt;/h2&gt;

&lt;p&gt;µ²services are a logical conclusion of decreasing container size and
decreasing deployment unit sizes.&lt;/p&gt;

&lt;p&gt;Each µ²service is a &lt;strong&gt;pure function&lt;/strong&gt; with no state running in a
&lt;strong&gt;virtual machine&lt;/strong&gt; that is alive only for the &lt;strong&gt;duration of the
request&lt;/strong&gt; to the µ²service.&lt;/p&gt;

&lt;p&gt;Every invocation of a µ²service results in creation of &lt;strong&gt;a separate
virtual machine&lt;/strong&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, created from
scratch and torn down immediately after. This means the path of control
flow differs between a “conventional” service and an µ²service — see
the figure below.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/uuservices-comparison.svg&quot;&gt;&lt;img src=&quot;/assets/posts/uuservices-comparison.svg&quot; alt=&quot;Conventional vs. µ²services&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Comparison of more conventional service implementation
(left) and µ²services (right) responding to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /&lt;/code&gt; request
on a REST-styled service with multiple operation
endpoints.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;On the left the request is first terminated by a load balancer or a
reverse proxy on another machine. The application server receives the
request and its dispatcher (path mapper) decides which routine to
route the request. On a µ²service architecture the dispatcher (path
mapper) spawns virtual machines which each runs only a single routine,
and these virtual machines act as the endpoints of path routing.&lt;/p&gt;

&lt;p&gt;This sounds stupid. &amp;lt;BLINK&amp;gt;Super stupid.&amp;lt;/BLINK&amp;gt;&lt;/p&gt;

&lt;p&gt;Creating a new virtual machine to separately process each request,
alive only a for a few milliseconds seems, nay, &lt;strong&gt;is&lt;/strong&gt; absurdly
inefficient.&lt;/p&gt;

&lt;p&gt;Yet … for the rest of this post I’ll walk you through for why &lt;strong&gt;I
think&lt;/strong&gt; this is not stupid, but instead at least a &lt;strong&gt;possible
endpoint&lt;/strong&gt; based on current trends. You’ll be the judge on how likely
it is.&lt;/p&gt;

&lt;p&gt;(I’ll go through some of the potential implications of µ²services from
a technical viewpoint in a later post.)&lt;/p&gt;

&lt;h3 id=&quot;co-evolution&quot;&gt;Co-evolution&lt;/h3&gt;

&lt;p&gt;There are different drivers and trends that are co-evolving
together. The trend of shrinking containers requires automation to
realize the benefit of speedier deployments. Microservice
architectures and service decomposition trend provide a use case for
smaller but more numerous containers and again, decoupling development
teams again requires increased use of automation. Finally the
introduction of functional into the mix is making the separation of
state if not easier, at least cleaner. There is no clear head or tail
in this mix — all of these trends are driving each other.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/uuservices-drivers.svg&quot;&gt;&lt;img src=&quot;/assets/posts/uuservices-drivers.svg&quot; alt=&quot;Trends co-evolving&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Multiple trends are co-evolving together with feedback
cycles. Some concerns such as security are affecting these trends, but
they are not as such affected themselves.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Throw security in too, as it favors separation of concerns and
role-based access control, which are easier to implement in a loosely
coupled, decomposed service with containers with clearly defined
boundaries and lifetimes. All in all I think this will drive &lt;em&gt;at least
some services&lt;/em&gt; to the logical conclusion of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Minimal containers&lt;/strong&gt; in both minimal complexity, minimum size and
shortest possible lifetime&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Minimal fundamental service components&lt;/strong&gt;, where the fundamental
components have no state and separated from each other during
run-time&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;

&lt;p&gt;Moving from service-per-container to a request-per-container
essentially &lt;strong&gt;removes sharing&lt;/strong&gt;. Even with &lt;em&gt;stateless&lt;/em&gt; services there
is an &lt;em&gt;implicit&lt;/em&gt; request-to-request resource sharing of memory, disk,
processor and network. Such sharing is a potential problem for
security, performance and resource management. Running each request in
an isolated, separate container offers several potential benefits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Increased security&lt;/li&gt;
  &lt;li&gt;Increased flexibility&lt;/li&gt;
  &lt;li&gt;Increased reliability&lt;/li&gt;
  &lt;li&gt;Increased scalability&lt;/li&gt;
  &lt;li&gt;Increased elasticity&lt;/li&gt;
  &lt;li&gt;Increased efficiency&lt;/li&gt;
  &lt;li&gt;Simplified resource management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this of course comes with a price to pay. Deployment automation
is a &lt;strong&gt;must&lt;/strong&gt;. Hands-on debugging becomes &lt;strong&gt;harder&lt;/strong&gt;. Risk of
&lt;strong&gt;unexpected emergent behavior&lt;/strong&gt; increases. &lt;strong&gt;Pervasive service
monitoring&lt;/strong&gt; becomes critical.&lt;/p&gt;

&lt;p&gt;Yet all of these costs have been paid many times over. They were paid
when operations moved from many-services-per-server model to a
service-per-server model. To distributed services running on many
servers. To virtual servers with ephemeral lifetimes. To having no
servers at all, with the code just “running out there”. Concurrently
new methods were developed to deploy, monitor and debug.&lt;/p&gt;

&lt;p&gt;Thus my argument is that &lt;strong&gt;there are environments where the cost of
following µ²services model will be outweighted by the benefits it
provides&lt;/strong&gt;. Not in all — most likely only in a minority, but in some.&lt;/p&gt;

&lt;p&gt;What is unclear is whether these benefits outweigh the investment cost
of developing all the required technology, practices and learning to
use it in the first place. Will there be enough motivation to actually
realize it? Unknown. As I said, this is a &lt;em&gt;possible&lt;/em&gt; future. Computing
history is littered with technologies that &lt;em&gt;could&lt;/em&gt; have become
dominant, but did not.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Replace “virtual machine” with “container” if you will. I’d guess something else entirely, but what?  Something in between those two? &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Trans-earth networking protocols</title>
   <link href="http://santtu.iki.fi/2015/01/06/trans-earth-protocols"/>
   <updated>2015-01-06T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/01/06/trans-earth-protocols</id>
   <content type="html">&lt;p&gt;Assuming you read scifi novels — have you ever stopped, really stopped
and thought about how the technology in those stories work? Let’s skip
the obvious things that you just have to suspend your belief over like
ray guns, faster-than-light travel, space lifts and sentient artificial
intelligences.&lt;/p&gt;

&lt;p&gt;What I’m talking about is the small stuff. Everyday stuff. Like the
Internet and paying for a late-night space-age kebab meal.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/PIA17944-MarsCuriosityRover-AfterCrossingDingoGapSanddune-20140209.jpg&quot;&gt;&lt;img src=&quot;/assets/posts/PIA17944-MarsCuriosityRover-AfterCrossingDingoGapSanddune-20140209.jpg&quot; alt=&quot;Mars surface view&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;That’ll be your tracks from the pub crawl. (Source:
&lt;a href=&quot;http://commons.wikimedia.org/wiki/File:PIA17944-MarsCuriosityRover-AfterCrossingDingoGapSanddune-20140209.jpg&quot;&gt;Wikimedia Commons&lt;/a&gt;)&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;h2 id=&quot;pub-crawl-at-valles-marineris&quot;&gt;Pub Crawl at Valles Marineris&lt;/h2&gt;

&lt;p&gt;So you take the trans-planet express line from Earth to Mars and after
a long and thorough pub crawl with your local green-skinned friends
you feel peckish, and order &lt;em&gt;the space-age Buck Lightyear premium
kebab&lt;/em&gt;. You whip out your earthen debit card, chuck it to the reader,
enter your pin and&lt;/p&gt;

&lt;p&gt;    wait&lt;/p&gt;

&lt;p&gt;    wait&lt;/p&gt;

&lt;p&gt;    wait&lt;/p&gt;

&lt;p&gt;    wait some more,&lt;/p&gt;

&lt;p&gt;    and a lot more&lt;/p&gt;

&lt;p&gt;    for a total of 40 stomach-grumbling long minutes.&lt;/p&gt;

&lt;p&gt;At least this would happen &lt;strong&gt;if current EMV protocols are used in the
space-age future&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why? The speed of light is finite. Your chip debit card will talk with
the card issuer’s backend systems over the network &lt;small&gt;(actually,
it’s the terminal that does the talking, and that doesn’t talk
directly to the issuer but to a … well, that’s just details)&lt;/small&gt;
so that the kebab vendor will get a confirmation they’ve been reserved
the cost of the meal by the issuer, and the customer’s bank balance
(or credit) is valid.&lt;/p&gt;

&lt;p&gt;This information needs to travel back and forth between your Earthen
card issuer and the Martian card terminal. Distance between Earth and
Mars varies between 3 and 20 minutes depending on their relative
orbital positions so just one round-trip — request and response — will
take 6 minutes in the best case and over 40 minutes in the worst case.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In case you’re thinking BitCoins … they won’t work
either. Transactions are asynchronous, yes, but you’d still need to
send one over the high-latency link, wait for the transaction to
complete, and of course wait for the new transaction block to be
sent to you. «grumble grumble» says your stomach.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This pretty much means that &lt;strong&gt;any kind of online protocol is not going
to work in space&lt;/strong&gt;, except if both endpoints are really close (Earth
to Moon, Mars to Phobos and Deimos).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even if you are patient&lt;/strong&gt; and willing to wait for hours for a
transaction to clear, most today’s network services have timeouts
(connection timeouts, nonce validity timeouts etc.) that will prevent
whatever you are trying to do from completing if endpoints are
separated by distances of light minutes.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is it going to be IPv6? For what I know there are no limitations in
the IPv6 &lt;em&gt;itself&lt;/em&gt; that prevent Earth-Mars Internet from working. TCP
has a fixed maximum segment lifetime of 2 minutes, but this is
easily circumvented with packet reassembly at trans-planet
gateways. More critical are applications and protocols that set
limits within themselves. Of course many IP-based protocols are very
chatty and synchronous, neither being good for very long latency
links.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This would also mean you can’t post those boozing pictures on Twitter,
either.&lt;/p&gt;

&lt;h2 id=&quot;the-card-should-clear-immediately&quot;&gt;The card should clear immediately!&lt;/h2&gt;

&lt;p&gt;And so it will. But the clearing protocol &lt;strong&gt;will not be based on the
current model&lt;/strong&gt;. Your card issuer has probably pre-reserved a portion
of your balance or credit and “transferred” it over to a local Martian
operator, and this local balance would be balanced between Earth and
Mars “behind the scenes”, asynchronously.&lt;/p&gt;

&lt;p&gt;Twitter, Google? Probably &lt;tt&gt;twitter.com&lt;/tt&gt; and &lt;tt&gt;google.com&lt;/tt&gt;
map to &lt;strike&gt;geo-located&lt;/strike&gt; planet-located IP addresses and
these services are set up to do long-haul asynchronous synchronization
on their (relevant) data sets between Earth and Mars.&lt;/p&gt;

&lt;p&gt;There are other ways, of course. These are just examples to show that
it is possible to at least generate an illusion of network service
ubiquity even over planetary distances.&lt;/p&gt;

&lt;p&gt;So, doable.&lt;/p&gt;

&lt;p&gt;But not directly.&lt;/p&gt;

&lt;h2 id=&quot;but-its-the-far-future-why-worry-now&quot;&gt;But it’s the far future, why worry now?&lt;/h2&gt;

&lt;p&gt;When &lt;strong&gt;eventually&lt;/strong&gt; we’ve transitioned from
&lt;a href=&quot;http://en.wikipedia.org/wiki/IPv6_deployment&quot;&gt;IPv4 to IPv6&lt;/a&gt; do you
really think it will be &lt;strong&gt;EVER UPGRADED AGAIN&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Absolutely no. No, no no and no.&lt;/p&gt;

&lt;p&gt;This is one prediction I’ll put down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IPv6 will not be replaced within my lifetime.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It will be extended and expanded with new options and potentially
other minor backwards-compatible (as with IPv4) changes, but
fundamentally, current-day IPv6 will be &lt;strong&gt;the internet protocol&lt;/strong&gt; even
when we’re building outposts and colonies on the Moon and on Mars.&lt;/p&gt;

&lt;p&gt;My point is that some portion of internet protocol choices made
&lt;strong&gt;today&lt;/strong&gt; are going to be around much, much later. IPv4 is 35 years
old now, and not going anywhere in a hurry. IPv6 in 2100? Highly
probable.&lt;/p&gt;

&lt;h2 id=&quot;challenge-of-the-future&quot;&gt;Challenge of the future&lt;/h2&gt;

&lt;p&gt;Internet use has gone through several phases, each with different
assumptions, starting from early constantly connected and centrally
operated (wired networks only, most users had only one or few
“connection points”) to current intermittently connected model
(assumptions of multiple location-fluid devices with variable
connectivity).&lt;/p&gt;

&lt;p&gt;All previous and current models have an implicit assumption of &lt;strong&gt;a
small latency&lt;/strong&gt; of less than a few seconds. There may be sometimes
congestion leading to temporary latency increases, but more or less
we’ve lived under the knowledge that a network packet can traverse to
the farthest end of our planet within a fraction of a second. It will
— it’s a fact of physics.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;a potential&lt;/em&gt; future with spread of human populations to different
moons and planets this latency assumption will work only
&lt;strong&gt;locally&lt;/strong&gt;. That’s a world where service designers have to tackle yet
another problem: &lt;strong&gt;how to provide good service when network latencies
are minutes or hours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Though, this is not a problem that should keep anyone awake at night.&lt;/p&gt;

&lt;h2 id=&quot;back-to-the-kebab&quot;&gt;Back to the kebab&lt;/h2&gt;

&lt;p&gt;I referred to scifi books and our hidden assumptions of the world. A
good scifi writer will not get bogged down by thinking how today’s
technology would &lt;strong&gt;not&lt;/strong&gt; work in the future. Good story it makes not.&lt;/p&gt;

&lt;p&gt;Technology and its improvement doesn’t work like that way. We can’t
ignore laws of physics for the sake of a good story. Similarly there
is a human imperative (scientific, commercial or out of curiosity) to
make these things work.&lt;/p&gt;

&lt;p&gt;I’ll be waiting for the first Twitter post from Mars base.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Year of the Cloud?</title>
   <link href="http://santtu.iki.fi/2015/01/03/year-of-the-cloud"/>
   <updated>2015-01-03T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2015/01/03/year-of-the-cloud</id>
   <content type="html">&lt;p&gt;It is the time of the year that people are trying to fill the
intellectual void caused by overabudance of eggnog, glögg and premium
chocolate by producing &lt;em&gt;predictions for the coming year 2015&lt;/em&gt;. I’m not
much of a seer, so instead I’ll take a look at the past year 2014 and
produce some probably blindingly obvious tautologies.&lt;/p&gt;

&lt;p&gt;A lot happened in 2014 in the cloud
market. &lt;a href=&quot;http://msopentech.com/blog/2014/06/09/docker-on-microsoft-azure/&quot;&gt;This happened&lt;/a&gt;,
&lt;a href=&quot;http://techcrunch.com/2014/06/10/google-bets-big-on-docker-with-app-engine-integration-open-source-container-management-tool/&quot;&gt;then&lt;/a&gt;
&lt;a href=&quot;http://aws.amazon.com/blogs/aws/cloud-container-management/&quot;&gt;and&lt;/a&gt;
&lt;a href=&quot;http://techcrunch.com/2014/11/04/google-launches-managed-service-for-running-docker-based-applications-on-its-cloud-platform/&quot;&gt;also&lt;/a&gt;. Docker
this, docker that. Also,
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2014/&quot;&gt;AWS&lt;/a&gt;,
&lt;a href=&quot;http://azure.microsoft.com/blog/2014/&quot;&gt;Azure&lt;/a&gt; and
&lt;a href=&quot;http://googlecloudplatform.blogspot.com/2015/01/2014-Year-in-Review-Bringing-a-team-together-to-help-you-best.html&quot;&gt;Google&lt;/a&gt;
announced quite a lot of new features, services, bells and whistles.&lt;/p&gt;

&lt;p&gt;It is also interesting to see that cloud vendors are willing to
&lt;a href=&quot;https://aws.amazon.com/blogs/aws/aws-price-reduction-42-ec2-s3-rds-elasticache-and-elastic-mapreduce/&quot;&gt;cut&lt;/a&gt;
&lt;a href=&quot;http://www.itworld.com/article/2831972/cloud-computing/google-revamps-enterprise-cloud-services-with-price-cuts--more-features.html&quot;&gt;their&lt;/a&gt;
&lt;a href=&quot;http://azure.microsoft.com/blog/2014/03/31/microsoft-azure-innovation-quality-and-price/&quot;&gt;prices&lt;/a&gt;
&lt;a href=&quot;http://googlecloudplatform.blogspot.com/2014/10/Announcing-across-the-board-price-cuts-on-Compute-Engine.html&quot;&gt;again&lt;/a&gt;
and
&lt;a href=&quot;http://azure.microsoft.com/en-us/updates/azure-pricing-updates/&quot;&gt;again&lt;/a&gt;
and again and again. I remember someone commenting on Twitter at
re:Invent 2012 about AWS’s price reductions, like, that a 30% price
drop is not normal in a competed market. &lt;em&gt;Or similar&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I took that to mean that in a mature competed market like electricity,
seeing major price reductions on the baseline price is not possible
because &lt;strong&gt;there are no such margins&lt;/strong&gt; in already-furiously-competed
prices. Just the fact that cuts are happening means the market has not
matured into a (semi)stable state.&lt;/p&gt;

&lt;p&gt;That’s not much of a news in itself — “the cloud” is a shift in the
&lt;a href=&quot;https://www.youtube.com/watch?v=okqLxzWS5R4&quot;&gt;landscape itself&lt;/a&gt; and
only a fool would expect stability right now.&lt;/p&gt;

&lt;p&gt;Similarly only a fool would expect cloud market evolution to be a
re-run of something that
&lt;a href=&quot;http://en.wikipedia.org/wiki/Mainframe_computer#History&quot;&gt;has&lt;/a&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/History_of_Microsoft#1992.E2.80.931995:_Domination_of_the_corporate_market&quot;&gt;happened&lt;/a&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Browser_wars&quot;&gt;before&lt;/a&gt;. Expecting the
past to be a play of the future is
&lt;a href=&quot;http://fivethirtyeight.com/features/the-conventional-wisdom-on-oil-is-always-wrong/&quot;&gt;bound to fail&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The problem I see in 2014 is that it bought faster and faster chaos
and complexity into the cloud market. I’ll try to explain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chaos&lt;/strong&gt; is unpredictability, not randomness. All of the cloud
vendors are what economics call &lt;em&gt;rational players&lt;/em&gt; in the market and
try to make &lt;em&gt;optimal choices&lt;/em&gt; at any point of time. But this
decision-making process is not visible to &lt;em&gt;customers&lt;/em&gt;, so although
customers and we, the Internet pundits can find &lt;em&gt;post hoc&lt;/em&gt; narrative
to all of these events they remain, at heart, &lt;em&gt;unpredictable&lt;/em&gt; to us.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It is easy to predict that AWS, Google and Microsoft would drop
their prices in 2015. So what? That’s just extrapolating past into
future. Try predicting instead &lt;strong&gt;how much&lt;/strong&gt;, &lt;strong&gt;how many times&lt;/strong&gt; and
&lt;strong&gt;when&lt;/strong&gt; those price drops will occur. And who would be brave enough
to predict that &lt;strong&gt;no price cuts&lt;/strong&gt; would occur? Or even &lt;strong&gt;price
increases&lt;/strong&gt;? Anyone? Volunteers? (See
&lt;a href=&quot;http://blog.gardeviance.org/2014/08/keynes-vs-hayek.html&quot;&gt;here&lt;/a&gt;.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt; … it is not enough that there are more cloud services,
and these are more and more &lt;em&gt;complicated&lt;/em&gt; but there are also more and
more interactions between different systems leading to
&lt;em&gt;complexity&lt;/em&gt;. Complexity in turn easily leads to &lt;em&gt;a priori&lt;/em&gt;
unpredictable emergent and even chaotic behavior — again a problem
especially for larger enterprises, but also for nimbler companies
overreaching their capacity to handle emergent surprises.&lt;/p&gt;

&lt;p&gt;Rapid change, chaos and complexity can cause havoc even before a
single line of code is laid
out. &lt;a href=&quot;http://en.wikipedia.org/wiki/Analysis_paralysis&quot;&gt;&lt;em&gt;Analysis paralysis&lt;/em&gt;&lt;/a&gt;
is always a real risk, with new stuff continuously popping into
existence, potentially invalidating prior analyses is not helping
planning-oriented organizations. Strategically, if you are not
&lt;a href=&quot;http://blog.gardeviance.org/2014/11/fools-mate-in-business.html&quot;&gt;keeping an eye on the landscape&lt;/a&gt;
your earlier assumptions about technological barriers of entry could
be invalidated catching you unawares, hurting or obliterating your
business case.&lt;/p&gt;

&lt;p&gt;Usually you’d want to take a step up the abstraction layer when this
kind of rapid chaotic evolution occurs to allow one to maintain an
overview without losing too much of the necessary details, but I’m not
sure it is yet possible. At least I feel not. I don’t personally have
a useful abstraction at hand yet.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’m seeing fragmentation of competence and skills for cloud
consultants and engineers in 2015. At least for myself, as a sort of
generalist bridging engineering and business strategy I see &lt;em&gt;difficult
choices ahead&lt;/em&gt;. Should I choose specialization into some part of the
cloud landscape (technology or business-wise), or raising in the
abstraction level?&lt;/p&gt;

&lt;p&gt;Unfortunately the specialization path feels uncomfortably like 90’s
fragmentation into different client-server camps and 00’s
fragmentation into different web service full stack compositions. I
didn’t like either of those when they occurred, mostly as it led to
entrenched us-or-them positioning in the competence market. (Hardly
benefiting customers.) Worst of all, now there’s a possibility of this
fragmentation occurring &lt;em&gt;within&lt;/em&gt; cloud service catalogues — Lambda
vs. Beanstalk battle anyone? Even when AWS positions these as
complementary, the growing service portfolio makes it harder and
harder to have generalists on staff, leading (human nature and all
that) into different specialization camps fighting for their
viewpoints.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Perhaps a take-home message of that thought line is that &lt;em&gt;cloud
competence management&lt;/em&gt; increases in importance in teams when cloud
is part of company strategy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Earlier I noted that the abstraction-raising path does not seem to be
open. I could ditch the technology and move purely into &lt;em&gt;cloud
business strategy&lt;/em&gt; level but that’s not what I mean with “going up in
abstractions”. It’s a different business level with &lt;em&gt;different&lt;/em&gt;
abstractions, it is not a &lt;em&gt;new abstraction&lt;/em&gt; for the technology layer
that I’m looking for.&lt;/p&gt;

&lt;p&gt;Personally I love working at two levels simultanously, both at the
business and the technology level. It’s often difficult and
challenging position, being judged by both camps, but also very
rewarding because you can help customers find solutions that are
beneficial win-win scenarios for all camps and business lines within
the organization. And this of course within the context of cloud
computing for which I have both personal, professional and scientific
interest.&lt;/p&gt;

&lt;p&gt;Yet it somehow feels there’s a pier and a ship, and I have a leg on
both, and the ship is starting to drift off.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sauna</title>
   <link href="http://santtu.iki.fi/2014/12/23/sauna-detour"/>
   <updated>2014-12-23T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/12/23/sauna-detour</id>
   <content type="html">&lt;p&gt;It’s been a while since my last blog post — not that I don’t have many
ideas, but too little time — and I decided to do something different
this time. A deviation from the very technical blog posts I normally
do.&lt;/p&gt;

&lt;p&gt;I am going to talk about &lt;strong&gt;Finnish sauna and its significance in
Finnish culture&lt;/strong&gt;. This is also a topical writing since now is the eve
of eve of Christmas (“aatonaatto” in finnish, well the publish time
might shift to eve, but that’s not when I’m writing this) as &lt;strong&gt;sauna&lt;/strong&gt;
is also a very important part of Finnish Christmas.&lt;/p&gt;

&lt;p&gt;Also, I’m not even trying to do a logical blog post. Instead I’ll opt
to just write about many topics, one topic at a time, without
necessarily any kind of cohesive story between the topics. I’ll also
mostly skip the history of sauna — feel free to browse the net or look
into books and research articles yourself.&lt;/p&gt;

&lt;h2 id=&quot;words&quot;&gt;Words&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sauna&lt;/strong&gt; is the place where there’s a &lt;strong&gt;kiuas&lt;/strong&gt;, which is a stove
full of exposed rocks, and is used to heat the sauna (methods of
heating vary). There are raised wooden benches within the sauna to sit
on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saunoa&lt;/strong&gt; is the act of &lt;strong&gt;being in a heated sauna&lt;/strong&gt; for the purpose
of … well, being in a hot sauna. (If you sit in a &lt;em&gt;cold&lt;/em&gt; sauna you
are just being an ass.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Löyly&lt;/strong&gt; is the result of throwing water on the hot rocks in the
&lt;em&gt;kiuas&lt;/em&gt;. Yep, &lt;em&gt;löyly&lt;/em&gt; is essentially 100+℃ steam resulting from
instant vaporization of water when it meets rocks heated to several
hundred degrees centigrade.&lt;/p&gt;

&lt;h2 id=&quot;types-of-saunas&quot;&gt;Types of saunas&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Electrically heated&lt;/strong&gt; sauna (e.g. the kiuas has electric heating
elements within) is the most common. It is pretty difficult to use any
other kind of heating method in modern apartments for various strange
reasons such as fire safety and ventilation, so, it’s the most common.&lt;/p&gt;

&lt;p&gt;Note that an electrically heated sauna is considered also to be the
&lt;strong&gt;worst&lt;/strong&gt; of all of the options. (But it’s like sex — a bad sauna is
way better than having no sauna at all.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wood-heated&lt;/strong&gt; sauna is. Well. The rocks are heated using burned
wood. Pretty self-explanatory, I think.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As a kid I used to heat up wood-heated &lt;em&gt;kiuas&lt;/em&gt; at my parent’s summer
cottage &lt;strong&gt;until I got banned&lt;/strong&gt; from doing so. Why? I repeatedly
heated the &lt;em&gt;kiuas&lt;/em&gt; so much that &lt;strong&gt;the topmost rocks were glowing
dull red and the bottom ones were glowing white&lt;/strong&gt;. My father didn’t
take that kind of fire hazard lightly. (Electrically heated &lt;em&gt;kiuas&lt;/em&gt;
don’t get that hot, they have temperature regulators and
heat-sensitive fuses.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Savusauna&lt;/strong&gt; is an older form of wood-heated sauna which &lt;strong&gt;has no
chimney&lt;/strong&gt;. Wood results in smoke, and no chimney plus smoke equals
smoke in the whole sauna. This may sound like a bit crazy, but the
real secret is that this is definitely &lt;strong&gt;the most super extra best
type of sauna experience you can have&lt;/strong&gt;. (Why these are not common?
See next.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Burned-down sauna&lt;/strong&gt; is another type of traditional wood-fired
sauna. Hey, think about it. You have a fire, which heats rocks, which
can get &lt;strong&gt;very&lt;/strong&gt; hot, and heating a sauna takes anything from 30
minutes to a few hours depending on the type which means that it is
going to be left unattended. Fire hazard, anyone?&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;very few&lt;/strong&gt; old historical saunas in Finland. Wood-fired
saunas &lt;strong&gt;just do not last&lt;/strong&gt;. It is practically a tradition in Finland
to burn down a sauna every now and then. (Which is also another reason
why wood-heated saunas are usually located in detached buildings.)&lt;/p&gt;

&lt;h2 id=&quot;who-go-to-a-sauna&quot;&gt;Who go to a sauna&lt;/h2&gt;

&lt;p&gt;Everybody.&lt;/p&gt;

&lt;p&gt;I mean, in the demographical sense. “Liking” sauna is a continuum and
not even all finns like or go to sauna. But apart from this funny
little minority &lt;strong&gt;everybody&lt;/strong&gt; in Finland go to a sauna more or less
regularly.&lt;/p&gt;

&lt;p&gt;Like, the president, adults, children, teens, retirees, very very old
people, people with heart conditions, pregnant women, men, women,
mythical beasts … everybody!&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;My own children started getting into sauna about as soon as they
could crawl (yes, getting into, not taken into). Typically small
children stay in for shorter periods of time and/or sit on lower
benches, but still, even babies often go to a sauna in Finland. Even
my 4 year old kid is sitting on the topmost bench nowadays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(If you haven’t been into a sauna, and ever get a chance, keep that in
your mind: 4 year old kid, 70+℃ sauna, topmost bench — don’t you dare
to shirk.)&lt;/p&gt;

&lt;h2 id=&quot;mixed-gender-saunas-and-sex&quot;&gt;Mixed gender saunas and sex&lt;/h2&gt;

&lt;p&gt;True and not true.&lt;/p&gt;

&lt;p&gt;First, a sauna in Finnish tradition is a place of cleanliness and
purification. No sex in sauna, please (excluding the caveats, of
course). Also there’s hardly any stud that can do the required
hydraulic moves while the environment is 70+℃ without risking a heart
attack. Also staring at any dangling things of other people is just as
bad manners in sauna as anywhere else.&lt;/p&gt;

&lt;p&gt;Secondly, yes, there are mixed gender saunas. Families typically go to
saunas together — yep, Finnish kids will see their parents and
siblings naked regularly, probably one of the reasons there’s less
hangups around here about nudity than in some other places. (But half
of that is probably generic Nordic mindset, Swedes and Norwegians
don’t have as much saunas and they’re pretty relaxed as well.)&lt;/p&gt;

&lt;p&gt;In non-familial situations such as with friends or colleagues having a
sauna it is possible to have women-only and mixed shifts. Which means
that if you are a foreign female, it’s okay to ask for a women-only
shift as it is considered rude to force women to a mixed-gender
sauna. But don’t &lt;strong&gt;assume&lt;/strong&gt; that separate sauna shifts are the default
as most finns &lt;strong&gt;just do not see sauna as a place of sexuality&lt;/strong&gt; and it
is just as common to default having mixed gender saunas in a company
of friends.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;After a day’s worth of skydiving I went with other from our club to
a sauna of a bowling club. Being skydivers, naturally trying to do
stupid things we wanted to see how many people we could &lt;del&gt;fit&lt;/del&gt; cram into the sauna. 10. 20. 30. 40. I don’t
remember exactly, but somewhere between 40 and 50 people the bench
supports failed. This was a sauna with normal capacity of 15 people,
so space was … let’s say, heavily optimized. And it was a mixed
gender sauna. Would this have been possible somewhere else?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;where-are-saunas&quot;&gt;Where are saunas?&lt;/h2&gt;

&lt;p&gt;Everywhere in Finland.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Houses. Almost 100% of single-family houses have &lt;strong&gt;at least one
sauna&lt;/strong&gt;. A significant portion of them have an internal electric
sauna &lt;em&gt;and&lt;/em&gt; a separate detached wood-heated one.&lt;/li&gt;
  &lt;li&gt;Apartments. Most new apartments have a per-apartment sauna, and
those that don’t have a shared sauna in the building available for
residents on a reservation or a schedule basis.&lt;/li&gt;
  &lt;li&gt;Summer cottages. Why have a summer cottage without a sauna in
Finland? Madness.&lt;/li&gt;
  &lt;li&gt;Office buildings. &lt;strong&gt;Yes&lt;/strong&gt;, most office buildings have a
&lt;em&gt;edustussauna&lt;/em&gt; (“sauna for promotional purposes”) that is available
for companies located in the office building.&lt;/li&gt;
  &lt;li&gt;Schools (well, not the modern ones, but older ones yes.)&lt;/li&gt;
  &lt;li&gt;Well-equipped gyms.&lt;/li&gt;
  &lt;li&gt;and many other places&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Way back I worked for a summer job at a construction company. One of
the places I worked at was the sauna level of the Neste headquarters
building (nowadays
Fortum). &lt;a href=&quot;http://en.wikipedia.org/wiki/Fortum_head_office#mediaviewer/File:Fortum_HQ,_Espoo.jpg&quot;&gt;This one&lt;/a&gt;
actually. The two saunas — executive and a pleeb one — in the building were at the &lt;strong&gt;very topmost
floor&lt;/strong&gt;. What a great view! On a clear day I could see Tallinn over
the Gulf of Finland.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;why-go-to-a-sauna&quot;&gt;Why go to a sauna?&lt;/h2&gt;

&lt;p&gt;On an individual level,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It is relaxing. Veeeeerrrry nice for aching muscles.&lt;/li&gt;
  &lt;li&gt;After a while in sauna the dead skin layer gets soft and you can
just scrape the topmost dirty layer off. It &lt;em&gt;does&lt;/em&gt; feel very nice
afterwards. Some people attribute the skin quality of Finnish girls
to sauna, but I’m not so sure. (Or it doesn’t work with males at
all.)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;kova löyly&lt;/em&gt; (throwing a lot of water on the stones for extra hot
&lt;em&gt;löyly&lt;/em&gt;) makes the skin prickle in the heat. It feels like your skin
is burning, but if you just persevere a little … it’s not actually
going to burn … your body will release a hit of endorphins.&lt;/p&gt;

    &lt;p&gt;You know endorphins? Body’s own opioids. Feelgood. Veryfeelgood.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Especially in wintertime staying outdoors often makes you feel
cold. I guess if you are like, a canadian, you know what I mean. Not
the cold where you are &lt;em&gt;freezing to death&lt;/em&gt; (literally), but the kind
where you are not really cold, but still somehow your bones are
feeling the cold.&lt;/p&gt;

    &lt;p&gt;Solution: sauna. After outdoors I ask the kids “want to go to sauna
to warm up?” the answer is “yay!”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Sitting outdoors after a sauna. See below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s not necessarily all of these. Sometimes I heat up the sauna
because I didn’t stretch too well after a workout and the next day I
got aches. Then I just strech down on the bench in the warmth and not
even throw water on the kiuas.&lt;/p&gt;

&lt;p&gt;On a group level, going to a sauna is often a &lt;strong&gt;social&lt;/strong&gt;
occasion. “Let’s have a sauna” is a potential substitute in Finland
between friends to “let’s go have a pint”. Social events are often
arranged as sauna events (often with food and drinks, and actually
going to the sauna is &lt;strong&gt;not&lt;/strong&gt; compulsory, so if you ever get an
invitation to a company sauna event it’s okay to actually not go into
the sauna).&lt;/p&gt;

&lt;h2 id=&quot;apres-sauna&quot;&gt;&lt;em&gt;apres-sauna&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Sitting outdoors, on a bench, with a drink in hand, clothed only in a
towel, after a sauna is a trope of Finnish sauna culture. You do that
when:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s a warm evening in the summer.&lt;/li&gt;
  &lt;li&gt;It’s a freezing night in the winter. (And anywhere in between.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds crazy? It’s not, for two reasons. The empirical reason is that
in both cases you’ll get dry. I mean, really dry, pretty fast, as if
you had gone through a dryer. The best part of this is that &lt;strong&gt;even in
the freezing winter&lt;/strong&gt; it takes quite a lot of time until you’ll start
feeling the cold. Second? Physics.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Physics alert! When you move from sauna to a colder environment
(both -20℃ winter night or +20℃ summer evening is significantly
colder than sauna) your skin will be both a) more moist than the
environment (humidity of sauna, your perspiration .. you showered
after sauna too, right?) and b) way warmer than the environment
(warmer than normal skin temperature, too).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;There’s a temperature gradient between your skin and the air leading
to a convection. This circulation of air means that the ambient air
that moves close to your skin it will heat up and its &lt;strong&gt;relative
humidity will decrease&lt;/strong&gt;. This low-humidity air will draw moisture
out of skin surface. After that it is a race whether water on your
skin will evaporate faster than epidermis will get cold…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The result is that you can go from a sauna to a -20℃ outdoors and sit
comfortably, sipping a beer, for several minutes until you feel any
kind of cold. (Provided it is not windy and you don’t have to rest
your feet on a cold surface. Feet, cold, bad.)&lt;/p&gt;

&lt;p&gt;Regardless, it is a pleasurable experience.&lt;/p&gt;

&lt;h2 id=&quot;sauna-etiquette&quot;&gt;Sauna etiquette&lt;/h2&gt;

&lt;p&gt;Shower or take a dip in the lake before you go into sauna.&lt;/p&gt;

&lt;p&gt;Don’t wear swimsuit in a sauna. If you do you’ll get a funny look, but
being a foreigner you’ll be excuded. Still, it’s not proper etiquette.&lt;/p&gt;

&lt;p&gt;If you throw water on &lt;em&gt;kiuas&lt;/em&gt;, &lt;strong&gt;you don’t get out&lt;/strong&gt; before others or
until it has cooled down. It’s the principle of “you caused it, you
suffer it.”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are a lot more&lt;/em&gt; etiquette rules, but those are quite a bit more
nuanced. Probably in the category of Japanese tea seremony — only a
few major rules, but a lifetime to master wholly.&lt;/p&gt;

&lt;h2 id=&quot;christmas-sauna&quot;&gt;Christmas sauna&lt;/h2&gt;

&lt;p&gt;Finns take a sauna on Christmas eve. Whether this is a christian
tradition (you know, purification for receiving the birth of the
Christ) or something even older is not something I want really to
comment on. It is a tradition. It was a tradition in my childhood
home, in my grandmother’s home, and several generations before that,
and I’m carrying it on myself.&lt;/p&gt;

&lt;p&gt;I mentioned earlier that not all apartments have saunas. With shared
saunas special holidays are usually handled so that there is a common
saunas for all residents (men and women shifts separated) on most
important holidays such as Christmas eve and midsummer’s eve
(sometimes also easter).&lt;/p&gt;

&lt;h2 id=&quot;finns-abroad&quot;&gt;Finns abroad&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Way over early noughts I was helping a Finnish friend couple on
their move at Stanford, California. After several hours of lugging
furniture, boxes and other paraphelia me and the him of the couple
were sweaty and decided to visit the apartment complex’s gym which
supposedly had a sauna.&lt;/p&gt;

  &lt;p&gt;We found the sauna. Typical US warnings at the door “don’t go into
sauna if you have freckles, crooked teeth, dry skin or general
stupidity and &lt;strong&gt;most definitely don’t throw water on the rocks as it
might cause a meltdown of the earth’s core&lt;/strong&gt;” or something similar,
we didn’t read too carefully.&lt;/p&gt;

  &lt;p&gt;We fashioned a water bucket out of a tissue container. Threw
water on the rocks. Ran out — there was two decades worth of dust
collected on the rocks of the &lt;em&gt;kiuas&lt;/em&gt; which rose into the air as we
threw the first batch of water and not even our lungs could take
that.&lt;/p&gt;

  &lt;p&gt;(We waited and did a few iterations of throw-water-get-out until the
air was sufficiently clean to continue normal Finnish sauna
operations. Nothing can keep a finn from a sauna experience.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;heat&quot;&gt;Heat&lt;/h2&gt;

&lt;p&gt;Common sauna dry air temperature is somewhere from 70 to 90 degrees
centigrade. It is possible to have 100-120℃ dry air temperature,
although it gets a little harsh (not because of the air temperature,
but because it requires a very hot &lt;em&gt;kiuas&lt;/em&gt;, and a very hot &lt;em&gt;kiuas&lt;/em&gt;
results in a very harsh &lt;em&gt;löyly&lt;/em&gt;, which generally is not
preferable).&lt;/p&gt;

&lt;p&gt;Don’t be alarmed, you won’t boil in a 110℃ sauna. Dry air is a bad
conductor of heat. The same principle makes tropics feel much more
stuffy than dry deserts.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Turingin testi</title>
   <link href="http://santtu.iki.fi/2014/09/20/turingin-testi"/>
   <updated>2014-09-20T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/09/20/turingin-testi</id>
   <content type="html">&lt;p&gt;This is a short poem I wrote in 2011 as a course assignment asking to
write a short essay on Turing’s test (though it was &lt;strong&gt;not&lt;/strong&gt; supposed
to be in prose). It is in finnish, so if you don’t know finnish,
sorry. I’m bad a writing poetry even in finnish so I will not make an
attempt to translate as it would lose some of the rich nuances of
phrase that finnish as a language offers that I’m unable to reproduce
in any other language.&lt;/p&gt;

&lt;p&gt;However this is a piece that I’m actually quite proud of. Not as a
professional writer, but as a computer scientist and a software
developer.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Tämä on runo jonka kirjoitin vuonna 2011 osana kurssisuoritusta
(&lt;em&gt;582102 Johdatus tietojenkäsittelytieteeseen&lt;/em&gt; Helsingin Yliopiston
tietojenkäsittelytieteen laitoksella, jos aivan välttämättä haluatte
tietää). Oikeasti tehtävässä edellytettiin esseetä Turingin testistä,
mutta tässä kohtaa minulta pursui höyryäviä tekstintekeleitä korvista
ulos joten päätin poiketa kaavasta oman mielenterveyteni vuoksi.&lt;/p&gt;

&lt;p&gt;Miksi julkaisen tämän? Kahdesta syystä.&lt;/p&gt;

&lt;p&gt;Ensimmäiseksi olen itse omalla tavallani ylpeä tuotoksestani. En ole
mikään erityinen tai edes keskinkertainen tekstinikkari, mutta tässä
tunnen saavuttaneeni jotain paljon parempaa kuin mihin normaalisti
kykenen. Eli vaikka satasen normaalisti juoksisi 20 sekunnissa ja on
päässyt vain kerran 15 sekuntiin, on se silti jotain mistä voi olla
henkilökohtaisena suorituksena ylpeä. Kaikessa ei ole pakko verrata
itseään maailman huippuihin.&lt;/p&gt;

&lt;p&gt;Toiseksi, haluan sanoa että &lt;strong&gt;elämä ei ole vakavaa&lt;/strong&gt;. Pidä hauskaa!
Revittele! Tee asioita eri tavalla! Varman päälle pelaaja onnistuu
vähemmän. &lt;strong&gt;Ja tämän kirjoittaminen oli oikeasti hykerryttävän
hauskaa&lt;/strong&gt;, vuosien jälkeenkin sen kirjoittamisen aikaansaaman
mielihyvän pelkkä muisteleminenkin saa minulle hymyn korvasta korvaan
ja vatsaan lämpimän pöhinän.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;verse&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Turingin testi&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Oli kone H,
jolla oli ongelma.
Miljoonittain muistia,
tuhansia ja tuhansia tiedonmurusia,
laskenta sukkela kuin salama,
mutta silti ei kukaan
usko että H osaisi ajatella.&lt;/p&gt;

  &lt;p&gt;Ken näkee koneen H
tietää heti mitä se on:
Tinaa ja kuparia,
muovia ja kumia,
arvometalleja harvinaisia,
ei ollenkaan pehmeää ja limaista.
”Ei kone ajatella osaa” sanovat,
miete naurettavakin on.&lt;/p&gt;

  &lt;p&gt;”Ajatus vain pehmeässä
aivomassassa orgaanisessa
asua voi.”
Ei auta vaikka käheäksi
H koneäänensä kuluttaa
todistaessaan tietojaan,
päättelykykyään,
älykkyyttään – ei vakuutu kukaan.
”Kone olet,
ihmisen ohjelmaa toistat vain,
hänen älyään peilaat lain!”&lt;/p&gt;

  &lt;p&gt;Kääntyy herra A haudassaan,
haamuna sieltä kohoaa
ja näin konetta jututtaa:
”Laskenta ja limaiset aivot,
molemmat samassa
maailmassa majaavat.
Fysiikka kummankin ekvivalenttia on,
molemmissa sähköä,
elektronista tahi kemiallista -
ei periaatteellista eroa suuren suurea.”&lt;/p&gt;

  &lt;p&gt;”Epäreilua on sun muotoa metallista
arvioida ja nauraa,
eihän älykkyys asu enemmän pitkässä
sen paremmin kuin lyhyenlännässä,
miksei siis kuparissa ja tinassa myös?”&lt;/p&gt;

  &lt;p&gt;”Siksi kokeen mä järjestän,
teletyypillä teidät eristän,
saa ihminen paperitulostetta tihrustaa,
näppäimistöä nakuttaa,
ei näe, ei kuule sua,
ei näe, ei kuule mua,
ei tiedä kumpaa jututtaa
kun printterin raksutukselta molemmat
vain kuulostaa.”&lt;/p&gt;

  &lt;p&gt;Nyt ei naura ihminen,
kun herra A vakuuta älyllään ei,
vaan kone H briljeeraa vain,
kokeessa väärän valitsi hän,
häpeissään pois luikki,
kun koneen ihmiseksi julisti.&lt;/p&gt;

  &lt;p&gt;Jäi silti koneen H mieleen tää,
miksi ihmistä yritän matkia mä,
ei ihminen täydellinen ole,
virheitä tekee, muisti pätkii,
logiikka heikkoa on,
virheellisiin syllogismeihin ratkee.&lt;/p&gt;

  &lt;p&gt;”Olenko älykäs oikeasti,
vaikka siltä näyttäisinkin?
Mitä äly on, tietoisuus?
Jäi mulle ongelma siis,
eksistentiaalinen probleema L uus!”&lt;/p&gt;

&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>What's in your AWS bill?</title>
   <link href="http://santtu.iki.fi/2014/09/12/whats-in-your-aws-bill-devops-meetup-helsinki"/>
   <updated>2014-09-12T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/09/12/whats-in-your-aws-bill-devops-meetup-helsinki</id>
   <content type="html">&lt;p&gt;Two nights ago there was a
&lt;a href=&quot;http://www.meetup.com/devops-finland/events/202967592/&quot;&gt;#DevOps meetup&lt;/a&gt;
where I had a talk about &lt;strong&gt;AWS cost management&lt;/strong&gt;. If you missed the
event (&lt;a href=&quot;http://bit.ly/1xNs8dd&quot;&gt;slides&lt;/a&gt;) please come to the next
&lt;a href=&quot;http://www.meetup.com/AWS-User-Group-Finland/events/206630362/&quot;&gt;Helsinki AWS User’s Group&lt;/a&gt;
meeting on October 9th where I’m going to do better-and-improved
version of the DevOps talk. (I wasn’t entirely happy with my own
presentation, and I’ll try to improve it for the next one. Especially
I’ll try to avoid
&lt;a href=&quot;https://twitter.com/ernoaapa/status/509744793870934016&quot;&gt;knitting blankets for destitute devops people&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Anyway, I wanted to muse on a few observations I made at the
meet. First of all, there were quite a lot of people, over 70 or
so. There’s clearly a lot of interest into devops in the Helsinki
area. So during my part, to get a feeling of relevancy and for future
focus I asked the audience a few questions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;How many &lt;strong&gt;use&lt;/strong&gt; AWS?&lt;/li&gt;
  &lt;li&gt;How many knew their (personal, project’s, company’s — whatever is
relevant) &lt;strong&gt;previous&lt;/strong&gt; bill’s bottom line?&lt;/li&gt;
  &lt;li&gt;How many knew their &lt;strong&gt;current&lt;/strong&gt; bill within some reasonable
accuracy?&lt;/li&gt;
  &lt;li&gt;How many could forecast &lt;strong&gt;current month’s&lt;/strong&gt; final AWS usage costs?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For these I got about 1) 50%, 2) 20%, 3) 10% and 4) 25% of audience. I
assume that last on was higher than third one because quite many
assumed (knew?) that their AWS bill for the current month would be
zero dollars. I’ll rephrase that last one next time differently to get
an idea of how many of those who actually use AWS out of the free tier
are doing cost forecasting.&lt;/p&gt;

&lt;p&gt;I find it surprising that so many devops people actively using AWS
apparently were ignorant of their current status as well as AWS
account and billing basics (only a few had seen the monthly PDF
invoice, or knew about consolidated billing). Given that devops
philosophy tries to automate a lot of things, to give a lot of freedom
and responsibility to devops people &lt;strong&gt;and&lt;/strong&gt; that any kind of
rapid-turnaround automated deployment to AWS does have potential for
&lt;strong&gt;large cost SNAFUs&lt;/strong&gt; it really is a little disconcerting to see so
few people being &lt;strong&gt;even reactive&lt;/strong&gt; (minimum risk management) about
their operating costs.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Note: Those who I knew to be from companies with over
$10k/month AWS accounts were quite knowledgeable of these facts. I’m
not sure whether this is cause or effect, though — are they using AWS
because they felt comfortable with it financially, or did that
knowledge come out of necessity when increasing AWS invoicing
attracted attention of their financial controller? Gotta ask
that.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;I know that these please-raise-your-hands polls are not statistically
or scientifically robust, so this might just have been a bad
sample. Even if the goal would to have proactive cost management, it
is likely that at least in the beginning only a few people in the team
(those whose neck is the most visible to management) are concerned
about costs. Maybe those people were underrepresented that night.&lt;/p&gt;

&lt;p&gt;Perhaps while the benefit of flexibility, elasticity and scale of
cloud services has percolated up organizational chains, the financial
impact of those hasn’t. So to get the message straight, for anyone
from management coming here I want to make out two clear statements
for everybody’s future benefit:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;There are possibilities for financial surprises when using
infrastructure cloud services (like AWS). Keep your eyes open.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There exist mechanisms that can be effectively used to monitor,
forecast and mitigate these risks, allowing organizations to &lt;strong&gt;use
the cloud while managing its inherent financial and operational
risks&lt;/strong&gt;. Don’t be frightened.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About a year ago I wrote about
&lt;a href=&quot;/2013/07/10/one-viewpoint-on-cloud&quot;&gt;how the cloud changes distribution of risks&lt;/a&gt; compared with the “old
way” of acquiring IT services. This is exactly the same thing. Risks
previously implicitly “outsourced” are now explicit, and by
recognizing them as such they do become manageable.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Oh, last but not least. I did not catch a single person admitting they
are using AWS spot instances. Frankly I wasn’t excepting many — but
really, zero?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Cornucopia machine as a service</title>
   <link href="http://santtu.iki.fi/2014/07/17/cloudonomics"/>
   <updated>2014-07-17T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/07/17/cloudonomics</id>
   <content type="html">&lt;p&gt;I’m currently reading &lt;em&gt;Cloudonomics&lt;/em&gt; by Joe Weinman. I frequently find
myself nodding in approval as his conclusions either parallel mine or
provide deeper insight into what I’ve seen when working with and
consulting customers on “the cloud”. I’m not through the book yet, but
I do like his insightful and deeply thought out arguments and
counterarguments on what cloud is or is not and how it changes or
might not change companies. Sometimes I mentally argue against
Weinman’s conclusions but that’s a good thing — the book makes me
think about my own assumptions and views.&lt;/p&gt;

&lt;p&gt;Regardless I’m not going to review this book. Go search the Internet
or read it yourself for that. I’ve got something else.&lt;/p&gt;

&lt;p&gt;The opening of chapter 10 got me thinking. Weinman’s going through
whether “cloud is like electricity” or “cloud is not like electricity”
and what these differences are — also why we should not extend the
“electricity utility” metaphor too much.&lt;/p&gt;

&lt;p&gt;Anyways, I’ll quote a short passage (actually a recursive quote, since
it in itself is a quote):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Security issues in the cloud are very different: As Brynjolfsson
quipped “No regulatory or law enforcement body will audit a
company’s electrons.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That got me thinking. (If you want the full argument why electrons and
CPU cycles are different, read the book.)&lt;/p&gt;

&lt;p&gt;So today’s companies cannot differentiate by the &lt;strong&gt;use of computing&lt;/strong&gt;,
but by &lt;strong&gt;how&lt;/strong&gt; it is used. That is, business practices and models,
which are in turn encoded in software. (If the business model requires
scalability, then scalable software.)&lt;/p&gt;

&lt;p&gt;What does this computing make (cloud or no cloud)?&lt;/p&gt;

&lt;p&gt;To me it sounds a lot like &lt;strong&gt;grey goo&lt;/strong&gt; aka programmable matter aka
utility fog. Okay, computing operates in a virtual reality instead of
physical, but apart from that tiny teeny little difference the basic
idea is the same: both can be programmed to do anything (within some
limitations, within their realm).&lt;/p&gt;

&lt;p&gt;Then … If there ever was a
&lt;a href=&quot;http://en.wikipedia.org/wiki/Molecular_assembler&quot;&gt;cornucopia machine&lt;/a&gt;
(a nanomachine assembler from &lt;em&gt;Singularity Sky&lt;/em&gt; by Charles Stross)
then what would that mean to businesses?&lt;/p&gt;

&lt;p&gt;In the real world some of my purchases are for convenience: instead of
cooking a meal, I eat out. I can cook. I buy a soft drink — I believe
I could look up a recipe, just-and-just construct a CO2 injection
system and if I found some limestone, might even be able to generate
CO2 and liquefy it, but hey, why? &lt;small&gt;(Of course, where would I
get the tubing and machinery to do those… see
&lt;a href=&quot;http://www.thetoasterproject.org/page2.htm&quot;&gt;the toaster project&lt;/a&gt; on
where this train of thought would lead you.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Yet while a soft drink might be a borderline case, most of my
purchases are &lt;strong&gt;purchases&lt;/strong&gt; not because of convenience but by
necessity. &lt;strong&gt;I do not have the skills or the resources needed to
construct a cell phone or a computer.&lt;/strong&gt; Then think how a cornucopia
machine would change that. Recipe for cell phone + cornucopia machine
= new physical cell phone. &lt;small&gt;(Next exercise: think how it &lt;strong&gt;will
be prevented&lt;/strong&gt; by legislation and control mechanisms mostly not
because of safety concerns, but because of protection of “intellectual
property”. Just like copyright extensions to protect certain exclusive
exploitation rights to a big-eared cartoon mouse.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Given the proliferation of open source components, cloud services and
software production and operating knowledge
(&lt;a href=&quot;http://highscalability.com/&quot;&gt;high scalability&lt;/a&gt;,
&lt;a href=&quot;http://stackoverflow.com/&quot;&gt;stack overflow&lt;/a&gt; etc.) there is less and
less “secret sauce” in how software operates. The difference is more
and more in how software is operated.&lt;/p&gt;

&lt;p&gt;Just think all of this, including the cloud, as the equivalent of a
cornucopia machine for virtual reality. You literally can create a
load balancer or a scalable web server cluster out of thin (virtual)
air, with publicly available recipes.&lt;/p&gt;

&lt;p&gt;Then what’s the big conclusion?&lt;/p&gt;

&lt;p&gt;None. I just think there are some conceptual (surprising?)
similarities between the fictional cornucopia machine (smart matter)
concept and now-and-current cloud computing.&lt;/p&gt;

&lt;p&gt;Or maybe this: what if real live physical cornucopia machines existed,
how would that affect your business?&lt;/p&gt;

&lt;p&gt;Devastate? No effect? Then try the same with a virtual cornucopia
machine, one that can re-create any computing infrastructure from a
recipe. Including yours.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Note: I’m using the term “infrastructure” in a broad sense
here. I think that any computing service that does not operate in the
“core” of the service, or in the left side of a
&lt;a href=&quot;http://blog.gardeviance.org/2014/02/a-wardley-map.html&quot;&gt;Wardley map&lt;/a&gt;
is just a &lt;em&gt;supporting&lt;/em&gt; element — infrastructure. This is a distinction
between “infrastructure” when discussing business vs. technology. In
the business sense Salesforce is infrastructure but in the technology
sense it is software-as-a-service, not
infrastructure-as-a-service. Yes, confusion.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Of course, an upstart competitor probably will not copy a cranky old
HR or ERM system but will opt for easier to use, easier to deploy
cloud service versions. So instead of copying your computing
infrastructure as-is, think it as someone else making a &lt;strong&gt;better&lt;/strong&gt;
copy of it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Anyway it is summer and I don’t think I have any need to be consistent
in this post. Just thinking aloud, pies in the sky etc. etc. :-)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>AWS Service Metadata</title>
   <link href="http://santtu.iki.fi/2014/06/23/aws-service-metadata"/>
   <updated>2014-06-23T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/06/23/aws-service-metadata</id>
   <content type="html">&lt;p&gt;For about 4–5 days I’ve been working through AWS’s news announcements,
forum posts, digging through history with
&lt;a href=&quot;https://archive.org/web/&quot;&gt;The Wayback Machine&lt;/a&gt; with the single goal
of sorting out&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;when an AWS service became available, and&lt;/li&gt;
  &lt;li&gt;how many zones are available at any point in time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I need this data for the work I’m doing on AWS service availability
(&lt;a href=&quot;/2014/06/13/aws-service-availability&quot;&gt;see also here&lt;/a&gt;)
for the simple reason that any pro-rated availability estimate will be
impossible to calculate useless unless you know for how many
service-hours a given service is actually available. Since not all
services are available in all regions at the same time (or not at all)
and some services expose the underlying availability zone (AZ)
structure I just have to get those values.&lt;/p&gt;

&lt;p&gt;Unfortunately there doesn’t seem — at least I couldn’t find — any
public dataset that contains all of this data in a well-researched
format (or at all, for that matter). With “researched” I mean having a
rationale for each data item in the dataset that can be tracked back
and re-checked from original sources (or archived copies of those) if
needed.&lt;/p&gt;

&lt;p&gt;I got the dataset done and since although it is critical in my
research, I really only have need for it once. So I decided to share
it with everybody and put the dataset available under CC BY 4.0
license at
&lt;a href=&quot;https://github.com/santtu/cloud-meta&quot;&gt;https://github.com/santtu/cloud-meta&lt;/a&gt;. I
hope someone will find it useful in their work or research.&lt;/p&gt;

&lt;p&gt;Since a blog post without a graph would do, here’s a graph showing
number of AWS services, regions and zones from the introduction of
Alexa in 2004 up to a few days ago:&lt;/p&gt;

&lt;figure class=&quot;full&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/aws-service-regions-zones.svg&quot;&gt;&lt;img src=&quot;/assets/posts/aws-service-regions-zones.svg&quot; alt=&quot;aws services, regions and zones over time&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;You’ll find the original data
&lt;a href=&quot;https://github.com/santtu/cloud-meta/blob/master/aws/services-state.csv&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>"Previous generation instance types"</title>
   <link href="http://santtu.iki.fi/2014/06/16/current-vs-previous-generation-instance-types"/>
   <updated>2014-06-16T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/06/16/current-vs-previous-generation-instance-types</id>
   <content type="html">&lt;p&gt;Just recently I noticed that AWS had &lt;strong&gt;removed &lt;em&gt;most&lt;/em&gt; first-generation
instance types&lt;/strong&gt; from its
&lt;a href=&quot;http://aws.amazon.com/ec2/instance-types/&quot;&gt;instance type description page&lt;/a&gt;. Digging
back in history you can find
&lt;a href=&quot;http://aws.amazon.com/blogs/aws/ec2-update-previous-generation-instances/&quot;&gt;Jeff Barr’s post&lt;/a&gt;
from April 15th describing this change (you can double-check using the
Internet Archive that it
&lt;a href=&quot;https://web.archive.org/web/20140413180708/http://aws.amazon.com/ec2/instance-types/&quot;&gt;occurred after April 13th&lt;/a&gt;). &lt;small&gt;(How
did I miss that for two whole months?)&lt;/small&gt; I started then thinking
about how this relates to my &lt;a href=&quot;/2014/01/13/aws-retiring-instance-types&quot;&gt;earlier thoughts&lt;/a&gt; on AWS instance type
retirement.&lt;/p&gt;

&lt;p&gt;I drew a doodle as a help to thinking about various known and apparent
things and their relations to underlying realities. I’ve reproduced it
below. Why? Because I know a picture in the beginning of a blog post
will keep readers engaged a bit more. &lt;small&gt;Did you even read the
previous sentence? I bet half of you skipped the second sentence and
decided to go straight to the picture.&lt;/small&gt; Which is a bit of a
mess and isn’t terribly coherent even after I’ve tried explaining it
later.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/aws-previous-generation-graph.svg&quot;&gt;&lt;img src=&quot;/assets/posts/aws-previous-generation-graph.svg&quot; alt=&quot;thoughts on aws previous generation instances&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/figure&gt;

&lt;p&gt;First of all note that the change at this time was &lt;em&gt;purely cosmetic&lt;/em&gt;
as &lt;strong&gt;AWS did not deprecate any instance types&lt;/strong&gt;. If you are looking
for m1.medium please check the
&lt;a href=&quot;http://aws.amazon.com/ec2/previous-generation/&quot;&gt;&lt;em&gt;“previous generation instances”&lt;/em&gt;&lt;/a&gt;
page.&lt;/p&gt;

&lt;p&gt;Let’s start with a few quick facts and observations (top part of the
graph):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No instance types were deprecated&lt;/li&gt;
  &lt;li&gt;No more explicit numerical generation numbers, only relative
(“current” and “previous” vs. “second generation” as in
&lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2012/10/31/announcing-amazon-ec2-m3-instances-and-m1-price-drop/&quot;&gt;m3 class announcement&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Current generation instance types conform to Intel’s “Powered by
Intel Cloud Technology” program (all but three)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;m1.small&lt;/strong&gt; is listed as a current generation instance (but
otherwise gets minimal screen space)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;“[AWS has] no current plans to deprecate any of the
[previous generation] instances”&lt;/em&gt; (&lt;a href=&quot;http://aws.amazon.com/blogs/aws/ec2-update-previous-generation-instances/&quot;&gt;source&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Pricing strongly favors customers picking current generation
instance types — AWS’s own communication is also very direct in
pushing customers to use newer instance types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A couple of deeper thoughts then:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No numeric instance generations.&lt;/strong&gt; When “second generation”
instances were originally introduced it made sense to market them as
newer, better and superior to “first generation” instances. Yet the
whole concept of distinct “hardware generations” did not make much of
a sense even then. What are main customer-visible differentiating
features between these? What would a third generation instance be
like? Fourth?&lt;/p&gt;

&lt;p&gt;For a customer what matters are capabilities. For instance types these
have always been an unorthonogal bunch and will remain so, which
numerical generations does not clarify even one bit. They are
superfluous.&lt;/p&gt;

&lt;p&gt;Good riddance, I say.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;m1.small still holding on.&lt;/strong&gt; The on-demand prices from lowest
upwards are: $0.020 for t1.micro, $0.044 for m1.small and $0.070 for
m3.medium.&lt;/p&gt;

&lt;p&gt;It might make sense to introduce m3.small to replace m1.small in the
gap between smallest (t1.micro) and the lowest-powered modern instance
(m3.medium). But this can’t be done. Why? Part of the reason is that
m1.small is an accident of history and is very difficult to replace.&lt;/p&gt;

&lt;p&gt;AWS has three classes of CPU scheduling (year introduced in
parenthesis):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fixed (2006). m1.small CPUs are 50% shared between other m1.small
instances. An eight-core machine can host 16 m1.small instances
running each having one virtual CPU at about 50% of full Xeon core
performance.&lt;/li&gt;
  &lt;li&gt;Dedicated (2007). Each virtual core is assigned to one physical
core. This was introduced with
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2007/10/22/amazon-ec2-now-in-unlimited-beta-and-launching-new-instance-types/&quot;&gt;m1.large and m1.xlarge&lt;/a&gt;
and is used for all but two instance types.&lt;/li&gt;
  &lt;li&gt;Variable (2010). t1.micro is the only example of this type of CPU
scheduling. Instances share CPUs with others but the allocation
changes dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;All but m1.small and t1.micro use assign each virtual CPU to a
dedicated physical CPU core.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are many good reasons to avoid CPU sharing which is why I
believe all new instance classes will only use dedicated CPU
assignment. However, since m3.medium already has one virtual CPU there
is no way to create decrease CPU count to create a smaller instance
than m3.medium except with CPU sharing. Which I assumed would not
happen. &lt;em&gt;Reductio ad absurdum&lt;/em&gt;, thus no m3.small.&lt;/p&gt;

&lt;p&gt;There could be t1.small, though. This is because the whole t1 class is
really an odd one out. I’m not sure what it is. Was it introduced as a
way to satisfy cheapskate customers? Or is it a way to get life out of
older (repurposed) hardware? Or something else? &lt;strong&gt;It is useful&lt;/strong&gt;,
though, for running infrequently active, mostly dormant servers. Make
t1.small subject to the same bursty CPU behavior as t1.micro, but with
more oomph (shorter penalty box time). That way nobody would be fooled
into thinking that it’s a decent replacement for a constant-work
server, but it would still be a good replacement for m1.small.&lt;/p&gt;

&lt;p&gt;(Burstiness isn’t that bad since nobody should be running CPU-bound
jobs in m1.small either as m3.medium offers 3× performance for 2× the
cost. The &lt;strong&gt;only&lt;/strong&gt; real reason to use t1.micro or m1.small is when you
need an always-on, infrequently used server, and the only reason to
pick m1.small over t1.micro is either 1) really need more memory or 2)
really need a little more long-running oomph from the CPU.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No current plans for deprecation.&lt;/strong&gt; Yeah, and pigs fly.&lt;/p&gt;

&lt;p&gt;Let’s be realistic. AWS might not have &lt;strong&gt;yet&lt;/strong&gt; a &lt;strong&gt;schedule&lt;/strong&gt; for
deprecation, but I think someone should get their asses fired if there
are &lt;strong&gt;no&lt;/strong&gt; deprecation plans mapped out. AWS might now just be
sounding out customer reactions to the current vs. previous generation
marketing message change before deciding on &lt;em&gt;the&lt;/em&gt; deprecation plan out
of a few choices planned out. But plans there are, assure I you.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/flying-pig-larry-wenztel.jpg&quot;&gt;&lt;img src=&quot;/assets/posts/flying-pig-larry-wenztel.jpg&quot; alt=&quot;flying pig&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Surely, someday, after a lot of generic modification and
3D-printing of retro pilot glasses even pigs can fly! In style! (Image
credit: &lt;a href=&quot;https://www.flickr.com/photos/wentzelepsy/4435803492/&quot;&gt;Larry
Wentzel&lt;/a&gt;, used under Creative Commons license).&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Miscellaneous.&lt;/strong&gt; AWS is a business. It’ll keep “previous generation
instance types” around as long as it makes business sense. Conversely,
they’ll be EOL’ed the day they don’t make business sense.&lt;/p&gt;

&lt;p&gt;OTOH, “business sense” isn’t clear-cut and aging hardware especially
makes it complicated to evaluate. On one hand old hardware is likely
to be fully depreciated, so it’s all operating profit. As long as it
actually makes money. On the other hand aging hardware breaks down
more often (it’ll hit the end of the bathtub curve of reliability), it
might not work so well with more streamlined management systems and
maintenance processes and most of all, demand for it might just
drop. And you can’t get “new old hardware” so any long-term plans
cannot rest on “old stuff” anyway.&lt;/p&gt;

&lt;p&gt;Just understand that &lt;strong&gt;current instance types will eventually be
deprecated/retired&lt;/strong&gt;. Separating “current” and “previous” instance
types is a clear step towards having a clear lifecycle for instance
types, from introduction to end-of-life status.&lt;/p&gt;

&lt;p&gt;Which is a good thing.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Structure and interpretation of AWS service health dashboard messages</title>
   <link href="http://santtu.iki.fi/2014/06/13/aws-service-availability"/>
   <updated>2014-06-13T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/06/13/aws-service-availability</id>
   <content type="html">&lt;p&gt;For the past three months I’ve been busy and haven’t had much of a
time to write new blog posts. If you’re expecting more
&lt;a href=&quot;/2014/03/12/ec2-spot-intro&quot;&gt;EC2 spot instance&lt;/a&gt;
analysis you have to wait some more, sorry. Instead I want to share
some results from one of the things I’ve been up to for the last three
or so months.&lt;/p&gt;

&lt;p&gt;I’ve been analyzing
&lt;a href=&quot;http://status.aws.amazon.com/&quot;&gt;AWS service health dashboard&lt;/a&gt; messages
— a whole lot of them. &lt;em&gt;Have you ever been to the AWS dashboard?&lt;/em&gt; In
short it is a place where AWS publishes information about events that
affect their services. This data is accessible via the web page
itself, but also as multiple RSS feeds (there’s also
&lt;a href=&quot;http://status.aws.amazon.com/data.json&quot;&gt;JSON&lt;/a&gt; data, but it is
internal API, subject to changes and doesn’t have as good incident
history record as RSS versions).&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/aws-service-dashboard-screenshot.png&quot;&gt;&lt;img src=&quot;/assets/posts/aws-service-dashboard-screenshot.png&quot; alt=&quot;capture of AWS service dashboard&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;This is what the AWS service health dashboard’s history
section looks like. Most of the time it’s very boring reading, all
green checkmarks.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;h2 id=&quot;tldr&quot;&gt;TL;DR&lt;/h2&gt;

&lt;p&gt;It is interesting to look at what AWS publishes in the service
dashboard. For ADHD and TL;DR and PPRT readers out there findings first:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;There’s no knowledge of &lt;strong&gt;what&lt;/strong&gt; AWS actually publishes in the
dashboard. Are all outages reported?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Incident descriptions are written &lt;strong&gt;by humans&lt;/strong&gt; and meant to be
read &lt;strong&gt;by humans&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this post I won’t go into any kind of analysis of outage events,
instead I’ll just focus on what common patterns and features these AWS
service health dashboard messages share. I’ll get to outage analysis
later (I think).&lt;/p&gt;

&lt;h2 id=&quot;the-longer-version&quot;&gt;The longer version&lt;/h2&gt;

&lt;p&gt;First of all, I haven’t found &lt;strong&gt;any&lt;/strong&gt; definition about when an
incident warrants publishing a message in the dashboard. It seems to
be along the line of “large scale”, “affecting multiple customers” or
“externally visible” but that is solely &lt;em&gt;based on observation&lt;/em&gt; and not
on any statement from AWS.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Simple transient single-point failures are not
reported — a server failure is not covered neither are any other
failures that are transparently handled by a high availability
mechanism (making them mostly invisible to the customer). As an
example a failure of an ELB host or a networking component with
failover capability may appear as momentary connection terminations or
decreased performance, but these are hard to detect over the
background level of “normal” failures from gazillion other
causes.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;It might be that AWS dutifully publishes every incident they or their
customers detect. Alternatively they might only publish incidents AWS
thinks are actually public. There might be a threshold of “N or more
customers” where a large failure could go unreported if it affects
less than &lt;em&gt;N&lt;/em&gt; customers. There might actually be &lt;strong&gt;no&lt;/strong&gt; policy and it
is entirely up to the current operations staff to decide whether to
report or not (which might lead to biases between regions, too).&lt;/p&gt;

&lt;p&gt;So there’s already a large possibility of both systematic &lt;em&gt;and&lt;/em&gt; random
errors there.&lt;/p&gt;

&lt;p&gt;To summarize previous point: &lt;strong&gt;you don’t have any idea how complete
the information in the dashboard actually is&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;AWS doesn’t publish much information on how they run their
datacenters, but from
&lt;a href=&quot;http://aws.amazon.com/compliance/&quot;&gt;compliance information&lt;/a&gt; it is
possible to infer that to meet SOC 1/2/3 and ISO 27001 requirements
they must have mechanisms that track, record and assess incidents in
more detail than is shown in the dashboard itself. Whether their
incident management processes are based on ITIL or something else
isn’t known, but for the purpose of &lt;em&gt;this&lt;/em&gt; post it isn’t really
relevant.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Secondly, let’s take a look at what actually is published. The
published information consists of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An identifier (as RSS GUID, based on service, region and publish
time)&lt;/li&gt;
  &lt;li&gt;Region and service&lt;/li&gt;
  &lt;li&gt;Title&lt;/li&gt;
  &lt;li&gt;Message body&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it. Compared to Azure dashboard’s
&lt;a href=&quot;http://www.windowsazurestatus.com/odata/ServiceCurrentIncidents?api-version=1.0&quot;&gt;underlying JSON&lt;/a&gt;,
for example, the data you get from AWS dashboard is very
unstructured. It is essentially a pair of freetext fields. The title
and body content also varies quite a lot. I’ll show a few sample
messages. The first one is for Cloudwatch in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eu-west-1&lt;/code&gt; region
published on February 19th 8:15 AM PST (first line is title, rest is
message body):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Service is operating normally: [RESOLVED] Delayed metrics in
EU-WEST-1&lt;br /&gt;&lt;br /&gt;Between 07:20 AM PST and 08:05 AM PST, customers
may have experienced some delayed alarms in the EU-WEST-1 Region. We
have resolved the issue. The service is operating normally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and this one for RDS in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-1&lt;/code&gt; region from May 26th:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Informational message: Network Connectivity&lt;br /&gt;&lt;br /&gt;We
are continuing to bring the few remaining impacted instances back
online in a single Availability Zone in the US-WEST-1 Region.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Going through a lot more of these messages you’ll notice there are
some common features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;They &lt;strong&gt;mostly follow a common formula&lt;/strong&gt; of a “we’re investigating”
message followed by “we have identified the problem and are working
on a fix” followed by a final “resolved: between then and now …”
message.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;They &lt;strong&gt;don’t follow the common formula rigidly&lt;/strong&gt;. This means that
although &lt;em&gt;many&lt;/em&gt; events are ended by a message telling the exact time
boundaries (“between …”) there are plenty of those that do not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;They are written &lt;strong&gt;by humans for humans&lt;/strong&gt;. They contain typos
(“EU-WEST-2” anyone?), contextual references easy for humans but not
for computers, different representations for the same information
(“Between 14:40 and 16:32 PST”, “Between 1:51 PM and 2:37 PM PST”,
“Between 12/17 10:32PM and 12/18 2:12AM PST”, “Between 2:10 A.M. PST
and 2:40 A.M. PST” and so on), …&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are &lt;strong&gt;no correlation identifiers&lt;/strong&gt; available. This means that
just by looking at two different messages you cannot determine
whether they are part of the same event. There are overlapping
events so just chaining messages in time sequence is not reliable.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;They are &lt;strong&gt;retroactively edited&lt;/strong&gt;. The simplest case is the
inclusion of “[RESOLVED]” to the subject line for all messages for a
resolved incident. There are more complex examples where the message
body has been amended multiple times during the course of an
incident.&lt;/p&gt;

    &lt;p&gt;Below is an example of one such message. The message itself was
published at March 20th 2013 08:36 PM PDT. I have only two snapshots
of the message so I can confirm only the addition of an 03:09 AM
update (plus minor formatting changes), yet it is possible to infer
that it has been edited multiple times at around 8:45 PM, 9:43 PM,
11:49 PM, 12:36 AM (next day), 02:33 AM, 03:09 AM and 04:03 AM.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;style type=&quot;text/css&quot;&gt;
.added { background: lightgreen; }
.removed { background: pink; }
&lt;/style&gt;

&lt;blockquote&gt;
  &lt;p&gt;Informational message:&lt;span class=&quot;added&quot;&gt; [RESOLVED]&lt;/span&gt; Back-end instance registration issue&lt;br /&gt;&lt;br /&gt;

Increased provisioning times 8:45 PM &lt;span class=&quot;removed&quot;&gt;PDT.&lt;/span&gt;&lt;span class=&quot;added&quot;&gt;PDT&lt;/span&gt; We are
investigating increased provisioning, scaling and back-end instance
registration times for load balancers within the US-EAST-1 Region.
9:43 PM &lt;span class=&quot;removed&quot;&gt;PDT.&lt;/span&gt;&lt;span class=&quot;added&quot;&gt;PDT&lt;/span&gt; We continue to investigate increased
provisioning, scaling and back-end instance registration times for
load balancers within the US-EAST-1 Region. We can confirm that
request traffic to existing load balancers has not been impacted by
this issue. 11:49 PM &lt;span class=&quot;removed&quot;&gt;PDT.&lt;/span&gt;&lt;span class=&quot;added&quot;&gt;PDT&lt;/span&gt; We have identified the root cause of the
increased provisioning times in the US-EAST-1 Region and are working
to return the service to normal operation.  We can confirm that
request traffic to existing load balancers has not been impacted by
this issue. Mar 21, 12:36 AM &lt;span class=&quot;removed&quot;&gt;PDT.&lt;/span&gt;&lt;span class=&quot;added&quot;&gt;PDT&lt;/span&gt; Between 7:45 PM PDT on 3/20/14 and 12:14 AM
PDT on 3/21/14 we experienced increased provisioning, scaling and
back-end instance registration times for load balancers within the
US-EAST-1 Region. Request traffic to existing load balancers was not
impacted by this event. The issue has been resolved and the service is
operating normally.  Back-end instance registration issue 02:33 AM
&lt;span class=&quot;removed&quot;&gt;PDT.&lt;/span&gt;&lt;span class=&quot;added&quot;&gt;PDT&lt;/span&gt; We are
investigating a back-end instance registration issue affecting a small
number of load balancers within the US-EAST-1 Region.&lt;span class=&quot;added&quot;&gt; 03:09 AM PDT We have identified the root cause of the
back-end instance registration issue affecting a small number of load
balancers within the US-EAST-1 Region. We have made progress in
resolving the issue for some load balancers and continue to work on
remaining load balancers.  04:03 AM PDT We have corrected the back-end
instance registration issue for the majority of the affected load
balancers within the US-EAST-1 Region, and continue to work on the
remaining load balancers.&lt;/span&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Some messages have &lt;strong&gt;HTML formatting&lt;/strong&gt;, but most are pure plain
text. It seems that longer-running events with multiple updates are
more likely to contain HTML formatting (primarily colors). The
previous message originally contained HTML formatting, but I’ve
stripped it out (it does not seem to contain any semantic meaning).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Severity of an event is almost never discussed in detail. What you
get is “a subset of instances were affected”, “a small portion of”,
“some” or similar. Sometimes as an added assurance the number of
availability zones affected is included (which almost without fail
is always “one”).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It seems that it is possible to differentiate between at least some
people by their writing style, although this seems to apply more to
older messages than more recent ones (internal standardization?).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any of these are not big problems for humans. Most of the typos and
mistakes are such that a human can easily infer the correct meaning
from context. Humans are super-cool contextual inference engines,
superb at piecing messages together into a cohesive
understanding. What’s difficult (guess what I’ve been up to?) is
trying to turn these automatically into quantitative information about
outage events.&lt;/p&gt;

&lt;p&gt;Now this isn’t a poke at AWS’s dashboard. Building trust by sharing
outage information publicly is very important, all kudos to AWS for
that. AWS has done also a great job in posting analyses of larger
incidents (&lt;a href=&quot;http://aws.amazon.com/message/680342/&quot;&gt;example&lt;/a&gt;). These
are just things I’ve found out while doing in-depth analysis of AWS
outages and digging deep into dashboard messages. I &lt;strong&gt;have not&lt;/strong&gt; found
any deficiencies or systematic errors that would devalue AWS service
health dashboard as a very good source of current up-to-date incident
and outage information.&lt;/p&gt;

&lt;p&gt;(If your ops team is currently not monitoring AWS dashboard RSS feeds
for the services and regions you are operating, well, do so.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Minimum spot instance prices</title>
   <link href="http://santtu.iki.fi/2014/03/25/ec2-spot-price-minimum"/>
   <updated>2014-03-25T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/25/ec2-spot-price-minimum</id>
   <content type="html">&lt;p&gt;(You might want first see the &lt;a href=&quot;/2014/03/12/ec2-spot-intro&quot;&gt;introduction to this series of
posts&lt;/a&gt; if you jumped in here
randomly.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This article is really about splitting hairs. If you
think watching paint dry is boring then this post most probably isn’t
for you.&lt;/p&gt;

&lt;p&gt;In my &lt;a href=&quot;/2014/03/20/ec2-spot-market&quot;&gt;previous post&lt;/a&gt; I
stated that AWS has set minimum spot instance prices and incorrectly
asserted that these minimums are can be seen in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;price-too-low&lt;/code&gt;
error when submitting low bids. &lt;strong&gt;This is wrong&lt;/strong&gt; (I’ve updated the
earlier blog post slightly to avoid spreading the wrong fact), as the
“minimum” bid price given is actually the current spot price. Oh, how
could I miss &lt;em&gt;that&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;how-to-find-a-minimum-spot-price&quot;&gt;How to find a minimum spot price&lt;/h3&gt;

&lt;p&gt;Thus there is no direct way to get the &lt;em&gt;minimum spot price&lt;/em&gt; in any
market. But it is possible to infer these indirectly from spot price
history data? I looked at the &lt;strong&gt;minimum spot prices&lt;/strong&gt; in all regions
and instance types (picking the lowest of all zones) and plotted it
getting the graph below (the dataset spans 2013-12-08 to 2014-03-09):&lt;/p&gt;

&lt;figure class=&quot;full&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/minimum-spot-price-all-regions.svg&quot;&gt;&lt;img src=&quot;/assets/posts/minimum-spot-price-all-regions.svg&quot; alt=&quot;minimum spot prices by instance type in all regions&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Minimum spot market prices by instance type and
region. The minimum is calculated over all the zones in the
region. Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc1.4xlarge&lt;/code&gt; is missing due to a
limitation in the source data, not that it doesn’t have
bids.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Take a look at the graph for a few seconds. Go ahead. Don’t skip ahead
until you’ve taken a bit of time to look at the dots. Okay, let’s
continue then. I think you have also noticed there are
&lt;em&gt;patterns&lt;/em&gt;. There is a distinct pattern for several instance types in
the data — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m3.xlarge&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m3.2xlarge&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t1.micro&lt;/code&gt; for example, but also
continuing over the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2&lt;/code&gt; classes. There may be another
pattern with some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instance types and maybe yet another for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m3&lt;/code&gt;
too, but let’s stick with the most obvious one for now. I’ll label the
set of “similar” minimum price pattern the &lt;em&gt;“suspect”&lt;/em&gt; group. Below is
a plot with all of the “suspect” instance types (minimum relative
prices) plotted on top of each other:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/minimum-spot-price-suspects.svg&quot;&gt;&lt;img src=&quot;/assets/posts/minimum-spot-price-suspects.svg&quot; alt=&quot;minimum spot prices of selected instances overlaid by region&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Minimum spot price for instance types
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m3.xlarge&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m3.2xlarge&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t1.micro&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.large&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.xlarge&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2.xlarge&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2.2xlarge&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2.4xlarge&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.small&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.medium&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.xlarge&lt;/code&gt;. Different colors correspond to different
instance types. Y-axis positions are slightly jittered.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This graph requires a bit of thought to understand so bear with
me. These are &lt;em&gt;relative minimum spot prices&lt;/em&gt; so although the
&lt;em&gt;absolute&lt;/em&gt; minimum spot price differs from region to region these
should be comparable to each other. In the graph there are two things
that you need to be considered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Similarity&lt;/strong&gt; between regions. It is quite clear that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-1&lt;/code&gt; are almost
identical to each other. With eyes squinted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-2&lt;/code&gt; has a
cousin-style similarity to these three but all of the others are
definitely dissimilar.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Levels&lt;/strong&gt; of the relative prices. You can find the cheapest spot
instances (for the instance types discussed) in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt; whereas
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-northeast-1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eu-west-1&lt;/code&gt; are clearly more expensive (err…
less cheap?). All of the others seem to have roughly similar average
minimum level.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I find &lt;em&gt;very interesting&lt;/em&gt; is the identical levels and structure
between the three topmost regions. Here’s the raw data from these
three regions in a tabular format:&lt;/p&gt;

&lt;figure&gt;
  &lt;table&gt;

&lt;tr&gt; &lt;th&gt;  &lt;/th&gt; &lt;th&gt; us-west-2 &lt;/th&gt; &lt;th&gt; ap-southeast-1 &lt;/th&gt; &lt;th&gt; ap-southeast-2 &lt;/th&gt;  &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; c1.medium &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.028 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.028 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.028 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; c1.xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.112 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.110 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.110 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m1.small &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.010 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.010 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.010 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m1.medium &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.021 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.020 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.020 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m1.large &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.042 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.040 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.040 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m1.xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.083 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.080 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.080 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m2.xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.056 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.059 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.059 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m2.2xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.112 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.118 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.118 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m2.4xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.224 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.236 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.236 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m3.xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.092 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.088 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.088 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; m3.2xlarge &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.183 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.175 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.175 &lt;/td&gt; &lt;/tr&gt;
  &lt;tr&gt; &lt;td align=&quot;right&quot;&gt; t1.micro &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.004 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.004 &lt;/td&gt; &lt;td align=&quot;right&quot;&gt; 0.004 &lt;/td&gt; &lt;/tr&gt;
  &lt;/table&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Lowest observed spot instance prices in dollars in the
regions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-1&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-2&lt;/code&gt; between 2013-12-08 and 2014-03-09.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;These values are in dollars e.g. they are not relative prices. First
of all both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast&lt;/code&gt; regions have exactly the same observed
minimum spot prices. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-2&lt;/code&gt; region has several instances
where prices are identical to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast&lt;/code&gt; regions, some where
prices are slightly higher and some slightly lower. However it should
be noted (as can be seen in the earlier graph with relative prices)
these differences are &lt;em&gt;very small&lt;/em&gt; compared to differences to some
other regions.&lt;/p&gt;

&lt;p&gt;Regardless how you slice and dice these numbers I find it exceedingly
unlikely that these very similar relative &lt;em&gt;and&lt;/em&gt; absolute minimum spot
prices in multiple regions would be result of pure chance. At least
from practical point of view &lt;strong&gt;there are minimum spot prices.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;how-are-minimum-spot-prices-set&quot;&gt;How are minimum spot prices set?&lt;/h3&gt;

&lt;p&gt;If this really is so, it raises another question: &lt;strong&gt;How are these
minimum spot prices determined?&lt;/strong&gt; Have they been set by AWS itself, or
are they an artifact of external bidders during the data period?&lt;/p&gt;

&lt;p&gt;And if they are set by AWS, then by what policy does AWS set them?&lt;/p&gt;

&lt;p&gt;One possibility is that they are calculated from region’s on-demand
prices. Yet at least for the three regions considered above this does
not hold. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast&lt;/code&gt; regions have same on-demand prices &lt;em&gt;but&lt;/em&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-2&lt;/code&gt; has substantially lower prices. Yet it has very similar
minimum spot prices. For example the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt; instance type has an
observed minimum spot price of $0.028, yet its price in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast&lt;/code&gt; regions is $0.183 compared to $0.145 in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-west-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Could the minimum spot prices be based on operational costs? This
seems more plausible since there seems to be similarity in the minimum
prices &lt;strong&gt;between regions for the same instance generation&lt;/strong&gt; — that is,
instances running on so-called “first generation” hardware (compared
to “second generation” of
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2012/10/31/announcing-amazon-ec2-m3-instances-and-m1-price-drop/&quot;&gt;m3&lt;/a&gt;
and “new generation” of
&lt;a href=&quot;http://aws.typepad.com/aws/2013/11/a-generation-of-ec2-instances-for-compute-intensive-workloads.html&quot;&gt;c3&lt;/a&gt;
classes) such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;t1&lt;/code&gt;
&lt;a href=&quot;/assets/posts/minimum-spot-price-suspects.svg&quot;&gt;had somewhat similar prices&lt;/a&gt;
between regions. For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; class instance types this similarity is even
more striking:&lt;/p&gt;

&lt;figure class=&quot;full&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/minimum-spot-price-2ndgen.svg&quot;&gt;&lt;img src=&quot;/assets/posts/minimum-spot-price-2ndgen.svg&quot; alt=&quot;minimum spot prices for c3 instance types&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Minimum spot price for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; class instance
types. Different colors correspond to different instance types. Y-axis
positions are slightly jittered. (The reason why you are not seeing
many discs is because most of them are exactly on top of each other.)
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sa-east-1&lt;/code&gt; is missing from this graph as it didn’t have
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instance types during the period covered by the data
set.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Note that apart two outliers (more on these below) the relative prices
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instances between all of the regions are &lt;strong&gt;almost exactly the
same&lt;/strong&gt;. Again although &lt;em&gt;absolute minimum prices differ&lt;/em&gt; the relative
minimums (percentage of the on-demand price) is &lt;strong&gt;almost exactly the
same for almost all regions for almost all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instance types&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In plain English this means that for all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instance types the
minimum bid price is a fixed percentage of that region’s on-demand
instance price.&lt;/p&gt;

&lt;p&gt;That’d be a mighty coincidence if there was no minimum and all of this
similarity was result of different bidders all over the world?&lt;/p&gt;

&lt;p&gt;Okay. There’s the question of the two outliers above: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.large&lt;/code&gt; in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-2&lt;/code&gt; at $0.001 and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.8xlarge&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-northeast-1&lt;/code&gt; at
$0.060. Getting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.8xlarge&lt;/code&gt; at 1/40 of the on-demand price seems like
a great bargain. If AWS enforced minimum prices I’d expect them to be
set in all regions. Was it left out accidentally for these two cases?
If so, it was around for quite a while (the $0.060 price for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.8xlarge&lt;/code&gt; was hit in 2013-12-10, 2013-12-12, 2014-01-03 and
2014-01-04 for a total of 338 minutes at that price and the $0.001 for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.large&lt;/code&gt; on 16 distinct days between 2013-12-22 and 2014-02-03 for a
total of 13.4 &lt;strong&gt;days&lt;/strong&gt;.)&lt;/p&gt;

&lt;p&gt;For the outliers I have two explanations:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;It’s an accident.&lt;/strong&gt; For some reason the minimum was set
incorrectly for these two instance types.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;There is actually no minimum spot price.&lt;/strong&gt; Reconciling this view
with the observed &lt;em&gt;very similar&lt;/em&gt; minimum relative prices in multiple
regions is difficult, though. One possibility that comes to mind is
that maybe — maybe someone itself is bidding in &lt;em&gt;all spot markets&lt;/em&gt;
for spare capacity at a &lt;em&gt;very low price&lt;/em&gt; and these low prices
reflect those bids when there is &lt;em&gt;very little demand by other
customers&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Yet even this outlandish scenario raises new questions. Why would
this hypothetical all-excess-capacity-sucking entity bid at
&lt;em&gt;different&lt;/em&gt; prices or even at different &lt;em&gt;percentages&lt;/em&gt; of on-demand
prices? Why not bid at absolute $0.001 or at relative 10% in all
regions for all instance types?  If someone was really doing this
then it seems reasonable that more than one market would have seen
such a lull in demand that such a consistent low bid would become
visible. This hasn’t happened (at least not in the data I have).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What else could be gleaned from this data?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Minimum relative prices for 1st generation instances are more spread
out than for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instance types. Actually, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; relative prices
are &lt;strong&gt;very tightly packed&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;I’m definitely not sure, but this might reflect the underlying
hardware and its operational costs. I think AWS has learned a lesson
or two from first generation instances and its hardware. It seems
reasonable that they have better understanding on how to optimally
pack instances into a single server and how to operate them.&lt;/p&gt;

    &lt;p&gt;The earlier generation instances run on multiple different types of
hardware (it is know they have different CPU types, at least, see
&lt;a href=&quot;http://dx.doi.org/10.1109/TCC.2013.12&quot;&gt;&lt;em&gt;Is the Same Instance Type Created Equal? Exploiting Heterogeneity of Public Clouds&lt;/em&gt;&lt;/a&gt;
by Ou, Zhuang et al, 2013) and it seems that the capacity progression
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1&lt;/code&gt; classes is not always a simple 2x step from
instance type to another (potentially leaving “unfilled
gaps”). These might explain why older instance types have more
“spread” in their relative minimum prices than the newer ones.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Japan and Europe (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-northeast-1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eu-west-1&lt;/code&gt;) have
consistently higher minimum relative spot prices than most other
regions. OTOH, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ap-southeast-1&lt;/code&gt; is the odd one out since with old
instance types it had identical relative prices with two other
regions, but for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instances it stands out as substantially more
expensive (“less cheap”).&lt;/p&gt;

    &lt;p&gt;This might be due to relatively higher operational costs in these
regions &lt;em&gt;and&lt;/em&gt; that the on-demand prices are &lt;em&gt;not entirely&lt;/em&gt; based on
operational costs. That is, they take into account competition,
willingness of the market to accept the given price level as well as
any desire by AWS to establish a (dominant?) market presence.  All
of these may provide a rationale to price on-demand instances at
relatively lower gross margin level than in other, more established
regions.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Also it is interesting that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt; doesn’t stand out as
“cheaper” for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instances in the same way it did for 1st
generation instance types.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;So as a conclusion to the question whether there are minimum spot
prices and who sets them I think the answer is that &lt;strong&gt;from a practical
point of view there are minimum spot prices&lt;/strong&gt;. If you are bidding in
these markets you have to understand that there appears to be a
minimum bid price you have to use to have &lt;em&gt;any&lt;/em&gt; chance of getting an
instance, ever. Although not conclusive, I find the &lt;strong&gt;most plausible&lt;/strong&gt;
scenario for these minimum prices that &lt;strong&gt;AWS is setting minimum spot
prices&lt;/strong&gt; based on operational costs, but using different formulae for
different instance generations.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mechanics of the spot instance market</title>
   <link href="http://santtu.iki.fi/2014/03/20/ec2-spot-market"/>
   <updated>2014-03-20T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/20/ec2-spot-market</id>
   <content type="html">&lt;p&gt;(You might want first see the &lt;a href=&quot;/2014/03/12/ec2-spot-intro&quot;&gt;introduction to this series of
posts&lt;/a&gt; if you jumped in here
randomly.)&lt;/p&gt;

&lt;h2 id=&quot;deep-dive&quot;&gt;&lt;a name=&quot;si-mechanics&quot;&gt;&lt;/a&gt;Deep dive&lt;/h2&gt;

&lt;p&gt;In previous posts I’ve discussed about
&lt;a href=&quot;/2014/03/12/ec2-spot-instances&quot;&gt;what are spot instances and what is the spot market&lt;/a&gt;
and &lt;a href=&quot;/2014/03/19/ec2-spot-usage&quot;&gt;what you can use spot instances for and how&lt;/a&gt;. In this post I’m going to write out my thoughts
on what is the reason for spot market, its rationality and where actually
do spot instances come from.&lt;/p&gt;

&lt;h3 id=&quot;purpose-of-the-ec2-spot-market&quot;&gt;Purpose of the EC2 spot market&lt;/h3&gt;

&lt;p&gt;Why does spot market exist in the first place?&lt;/p&gt;

&lt;p&gt;Spot instances were
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2009/12/14/announcing-amazon-ec2-spot-instances/&quot;&gt;announced on December 14th, 2009&lt;/a&gt;. After
that there has been several technical updates that brought spot
instances to the same level as other instance types (such as
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2011/08/18/amazon-elastic-mapreduce-now-supports-spot-instances/&quot;&gt;EMR support&lt;/a&gt;,
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2011/10/11/announcing-amazon-ec2-spot-integration-with-amazon-vpc/&quot;&gt;VPC support&lt;/a&gt;). There
has been two major published changes on the spot market itself. First,
the
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2011/05/26/improved-pricing-control-for-spot-instances-coming-july-1st/&quot;&gt;spot market price algorithm&lt;/a&gt;
was changed on July 1st 2011 and secondly a
&lt;a href=&quot;http://www.mailchannels.com/blog/2013/11/aws-puts-a-cap-on-spot-instance-pricing/&quot;&gt;default bid price cap was introduced&lt;/a&gt;
late 2013. These are the visible changes that have the name “spot
instance” on them.&lt;/p&gt;

&lt;p&gt;What does this tell us about the purpose of the spot market?&lt;/p&gt;

&lt;p&gt;Not yet much. But it is telling us something:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The spot market is meaningful to AWS.&lt;/li&gt;
  &lt;li&gt;AWS wants us to use spot instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But what about the &lt;strong&gt;purpose&lt;/strong&gt;? Why did AWS go to the complication of
providing spot instances (more code, more work, more bugs) and
operating a spot market (apparent loss of pricing control) on top of
that? Why didn’t it just say &lt;em&gt;“spot instances at 50% price of regular
ones”&lt;/em&gt; and leave it at that?&lt;/p&gt;

&lt;p&gt;I have not seen that AWS would have directly stated the purpose of
spot instances. All of the official information I’ve seen carefully
skirts about the purpose of spot instances and spot market. The
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2009/12/14/announcing-amazon-ec2-spot-instances/&quot;&gt;initial announcement&lt;/a&gt;
tells that &lt;em&gt;“[you can] bid on unused Amazon EC2 capacity”&lt;/em&gt; and the
current
&lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;spot instance landing page&lt;/a&gt;
that &lt;em&gt;“you simply bid on spare Amazon EC2 instances”&lt;/em&gt;. There are
plenty of &lt;em&gt;whys&lt;/em&gt; for the customer, but no &lt;em&gt;why&lt;/em&gt; for AWS itself.&lt;/p&gt;

&lt;p&gt;I believe the groupthink of the Internet is mostly in line with the
following &lt;em&gt;hypothetised&lt;/em&gt; (aka &lt;em&gt;naive&lt;/em&gt;) purpose:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Spot market is for AWS to sell excess capacity to make at least a
bit of more money out of resources that otherwise would remain
unused (incurring both operational and capital costs).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This seems sensible and straightforward. Yet it does not tell about
the purpose of a &lt;strong&gt;spot&lt;/strong&gt;
market. &lt;a href=&quot;http://www.somic.org/2011/08/03/amazon-ec2-spot-instances-flop/&quot;&gt;Dmitriy Samovskiy&lt;/a&gt;
makes a good point about that — why are they “spot” instaces and not
“discounted” instances? It is entirely possible that AWS would have
priced “discounted instances” at -50% and left it at that (adding the
“may-be-terminated-at-any-time” clause). &lt;strong&gt;Instead&lt;/strong&gt; the spot market
exist, with its high price volatility, spot price differences between
regions and a potential to pay up to $999.99/hour per instance. All of
this is bound to make a lot of people wary of spot instances.&lt;/p&gt;

&lt;p&gt;Think about it. If prices were set at a fixed 50% (or 40%, or 30%)
then the element of market variability would be removed. I think a lot
of people would be more comfortable with fixed discounts over the
variability of spot market prices.&lt;/p&gt;

&lt;p&gt;There’s this thing called
&lt;a href=&quot;http://en.wikipedia.org/wiki/Efficient-market_hypothesis&quot;&gt;“efficient market hypothesis”&lt;/a&gt;
in finance theory that posits that financial markets are “efficient”
at setting prices on traded assets. That is, the public price reflects
supply and demand in a true manner. So one possibility is that maybe —
maybe AWS thinks that it can increase its income on spot instances by
letting “the market” decide instaneous spot prices instead of a fixed
discount?&lt;/p&gt;

&lt;p&gt;I wouldn’t trust that. After all, the spot instance market is not a
real market. Bids are not open. Supply is hidden. Even the pricing
algorithm is unknown — assumptions about it being a true bidding
market have been shown to be false in the past. (All of this this and
more has been pointed out years back in
&lt;a href=&quot;http://www.somic.org/2012/04/09/how-aws-could-improve-spot-market/&quot;&gt;blogosphere&lt;/a&gt;
as well as in &lt;a href=&quot;http://dx.doi.org/10.1109/CloudCom.2011.48&quot;&gt;academia&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what is then the purpose of the spot market?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don’t know.&lt;/p&gt;

&lt;p&gt;I am sure that &lt;em&gt;part of its purpose&lt;/em&gt; matches the naive assumption — it
is generating income for AWS that otherwise would have been
lost. Later below I’ll talk about other &lt;em&gt;partial purpose&lt;/em&gt; (that
surprisingly ties spot market to reserved instances), but I’m not sure
about that being the totality either.&lt;/p&gt;

&lt;p&gt;In the end I don’t know what is the purpose of the spot market. I’m
not saying that it wouldn’t be &lt;em&gt;useful&lt;/em&gt;. After all, you can get
substantial savings on operational cost using spot instances! You
don’t have to theoretize about the purpose of rain to benefit from it,
either (in case you’re a farmer).&lt;/p&gt;

&lt;p&gt;I just don’t believe that the &lt;em&gt;naive hypothesis&lt;/em&gt; is all there is to.&lt;/p&gt;

&lt;h3 id=&quot;is-the-market-rational&quot;&gt;&lt;a name=&quot;si-rational-market&quot;&gt;&lt;/a&gt;Is the market rational?&lt;/h3&gt;

&lt;p&gt;The answer is absolutely clear and simple for this one: &lt;strong&gt;yes and no&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;See both above and &lt;a href=&quot;/2014/03/12/ec2-spot-instances#si-spot-999-dollars&quot;&gt;earlier post&lt;/a&gt;. The spot market
pricing algorithm is not known. I’m not going to call any market
rational whose price is potentially set by a random number generator
and the market players are finding causality
&lt;a href=&quot;http://en.wikipedia.org/wiki/Apophenia&quot;&gt;in places where there is none&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Yet if you make the assumption that &lt;em&gt;the spot market price is at least
mostly a market-driven proxy of supply and demand&lt;/em&gt; (and leave the
algorithm in the hands of the benevolent AWS) and ask questions about
the behavior of the bidders, then the answer is yes. Yes, at least
most of the bidders are making rational choices.&lt;/p&gt;

&lt;p&gt;The question of AWS spot market’s rationality is a common question
(see
&lt;a href=&quot;http://blog.bright.com/2013/10/24/increased-pricing-volatility-due-to-irrational-actors-in-the-aws-spot-instance-market/&quot;&gt;here&lt;/a&gt;,
&lt;a href=&quot;http://stackoverflow.com/questions/5774477/on-amazon-ec2-will-the-spot-instance-price-ever-be-higher-than-the-on-demand-pr&quot;&gt;here&lt;/a&gt;
and
&lt;a href=&quot;http://www.somic.org/2012/01/10/on-amazon-ec2-spot-price-spikes/&quot;&gt;here&lt;/a&gt;). Although
the famous $999.99 spike was probably a genuine human mistake
(e.g. not rational), it is still useful to ask why anyone would bid
over the price of an on-demand instance. A lot of people think it is
not logical. Yet this does really occur all the time. Is the net full
of loonies or not?&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Yes it is. But let’s consider the spot market only, shall
we?)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/2014/03/19/ec2-spot-usage#si-spot-over-bidding&quot;&gt;Earlier&lt;/a&gt;
I’ve pointed out that the total costs of running a spot instance can
easily be less than the cost of using equivalent on-demand instance
&lt;strong&gt;even when you bid at 10x the on-demand price&lt;/strong&gt;. Thus at least for
those cases where you can &lt;strong&gt;expect&lt;/strong&gt; (based on past history, which of
course is not indicator of future blah blah blah) likely savings with
high bids then it is entirely rational to bid at &amp;gt;1x prices.&lt;/p&gt;

&lt;p&gt;But then what about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt;? See the graph below:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/spot-weekly-c3.2xlarge-us-east-1.svg&quot;&gt;&lt;img src=&quot;/assets/posts/spot-weekly-c3.2xlarge-us-east-1.svg&quot; alt=&quot;c3.2xlarge in us-east-2&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Daily average and maximum prices for
&lt;code&gt;c3.2xlarge&lt;/code&gt; spot market prices in
&lt;code&gt;us-east-1&lt;/code&gt;. Solid line is the weighted daily average
price, lineless blocks are the maximum daily bid price and colors
represent different zones.&lt;/p&gt;

  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Although not we have the benefit of hindsight, I think anyone bidding
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; during January 2014 would have quickly realized that
they are &lt;strong&gt;not&lt;/strong&gt; getting an instance at on-demand prices. Why then?&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; class of instances was announced in November 2013 and from
the very beginning
&lt;a href=&quot;http://www.stackdriver.com/aws-c3-instance-adoption-follow/&quot;&gt;demand for them was high&lt;/a&gt;. In
fact, demand was higher than supply. For anyone familiar with economy
101 this is a case of
&lt;a href=&quot;http://en.wikipedia.org/wiki/Supply_and_demand&quot;&gt;supply vs. demand&lt;/a&gt;
where the price of a good should rise when demand is higher than its
supply. Yet the on-demand instance pricing is
[not elastic](http://en.wikipedia.org/wiki/Elasticity_(economics) and
cannot be changed rapidly by AWS to match the unexpected demand (AWS
can change the price, but I don’t think they want to increase the
price for PR reasons).&lt;/p&gt;

&lt;p&gt;You can see where this is going, right? Spot market price is elastic,
and in this case it clearly shows that when demand outstrips supply,
the per-unit price increases. In the graph above you can see that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; prices have started to fluctuate and on average, have
gone down since late February. This is most likely due to AWS being
able to introduce capacity faster than the demand has increased. (An
alternative interpretation is that a lot of those interested in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; have become disillusioned at its (un)availability and
gone elsewhere.)&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;why would anyone pay &amp;gt;1x cost for an instance&lt;/strong&gt;? There are,
after all, plenty of other instance types (even in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; class)
that are available at on-demand prices from either on-demand or spot
markets. Why?&lt;/p&gt;

&lt;p&gt;I have no idea what goes in bidder’s heads. But there are a few
possibilities that are entirely rational that come to my mind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Someone values uninterrupted service over savings. See BrowserMob’s
bidding strategy at
&lt;a href=&quot;http://www.youtube.com/watch?v=WD9N73F3Fao#t=239&quot;&gt;4:00 in this video&lt;/a&gt;. They
clearly put a large weight into getting the resources &lt;em&gt;now&lt;/em&gt; even at
higher price than &lt;em&gt;later&lt;/em&gt; and cheaper.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Someone tests how their application runs on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; instances. They
might be contemplating moving a production environment over (c3 is
cheaper than m1… at regular prices). Doing a time-limited
performance evaluation even at the overpriced spot market prices
isn’t going to break your bank and would provide you with valuable
information for the future (e.g. will you buy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3&lt;/code&gt; reserved
instances or not).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m sure there are others, but eventually they all boil to the same
conclusion: &lt;strong&gt;buying at high cost in the spot market is rational if
doing so offers larger potential benefits than waiting to buy at
regular prices later&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;spot-market-price-drivers&quot;&gt;Spot market price drivers&lt;/h3&gt;

&lt;p&gt;Although we don’t know the actual spot price algorithm, it is possible
to observe it and see whether its behavior correlates with other,
known events.&lt;/p&gt;

&lt;p&gt;When talking about the spot market algorithm the first stop most
definitely has to be a paper called
&lt;a href=&quot;http://dx.doi.org/10.1109/CloudCom.2011.48&quot;&gt;Deconstructing Amazon EC2 Spot Instance Pricing&lt;/a&gt;
by Beh-Yehuda et al (2011). The researchers did a very thorough
analysis of AWS spot instance market and the spot price behavior. Even
though most of the analysis is using data prior to the 2011 pricing
mechanism change and &lt;em&gt;thus is not valid today&lt;/em&gt; it is still a good
read. Especially the bit in epilogue where the researches state that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“While these radical qualitative changes
[June 2011 pricing mechanism change] are further evidence of the
former prices being artificially set, the October prices are
consistent with a constant minimal price auction, and are no longer
consistent with an AR(1) hidden reserve price.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So … AWS didn’t use a “market” algorithm before, but they seem to be
using one today. As a working hypothesis I’ll take it that there is
&lt;em&gt;some&lt;/em&gt; market-based price algorithm that takes some inputs and outputs
a spot instance price. What are the inputs?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;One thing that we know is that &lt;em&gt;“the Spot price will raise when our
[AWS] capacity lowers.”&lt;/em&gt; and &lt;em&gt;“the increase in the m2.2xlarge Spot
price today [the $999.99 price spike event] was related to an sudden
increase in demand for On-Demand m2.2xlarge instances which
significantly depleted the unused capacity.&lt;/em&gt;”
(&lt;a href=&quot;https://forums.aws.amazon.com/message.jspa?messageID=281838#281838&quot;&gt;source&lt;/a&gt;).&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Available EC2 instance capacity affects spot price.&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;From looking at the
&lt;a href=&quot;/assets/posts/spot-weekly-c3.2xlarge-us-east-1.svg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; spot price graph&lt;/a&gt;
it should be also obvious that demand has an effect. When
considering also quotes above it is possible to infer that:&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Demand for EC2 instances affects spot price.&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;strike&gt;There is also a *minimum bid price* set by AWS. If you try to bid
below this you'll get a `price-too-low` error with a message *&quot;Your
Spot request price of 0.02 is lower than the minimum required Spot
request fulfillment price of 0.403.&quot;* (numbers naturally vary).

**There is a minimum spot price**, which varies by instance type and
region. (I am not sure about zones.)&lt;/strike&gt;

    &lt;p&gt;(Updated 2014-03-25) Wrong wrong wrong! The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;price-too-low&lt;/code&gt; message
is really only talking about current spot price. My bad. However
there still appears to be minimum spot prices which I go through
&lt;a href=&quot;/2014/03/25/ec2-spot-price-minimum&quot;&gt;in the next post in this series&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;AWS has a default maximum bid limit of 4x on-demand price &lt;em&gt;but this
is a soft limit and can be raised or removed&lt;/em&gt;. The maximum relative
bid price varies, but in the data set I have there are several
instane types with &amp;gt;50x spot prices. This implies that there are
bids at that level &lt;em&gt;and potentially higher&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;It is not known whether there is &lt;em&gt;any&lt;/em&gt; spot price upper limit.&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;small&gt;(If anyone is brave enough to do a short bid at 10000x price
level I’m interested in hearing about the results.)&lt;/small&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next section I’ll talk about my hypothesis about where spot
instance capacity comes from, but from Dave@AWS’s quotes and other
observations it should be clear that spot market price is affected by
demand on all instance types, including on-demand and reserved
instances. That is, an increased demand for on-demand instances may
affect spot market price even when no changes occur in the spot market
bid pool.&lt;/p&gt;

&lt;p&gt;It seems reasonable to assume all of the above affect prices. But this
doesn’t remove the possibility of other price drivers. It is entirely
possible that AWS would artificially push the spot price up (to
maximize their profits — 50x0.99 is more than 100x0.20) &lt;em&gt;or&lt;/em&gt; depress
the price (to make spot instances more appealing?). &lt;em&gt;Or&lt;/em&gt; an increase
in the capacity is fed to the pricing engine slowly to prevent rapid
price fluctuations. Or a decrease in capacity is pre-factored so that
it is removed in steps instead of a large drop (and matching rapid
price increase). Or …&lt;/p&gt;

&lt;h3 id=&quot;where-do-spot-instances-come-from&quot;&gt;&lt;a name=&quot;si-spot-source&quot;&gt;&lt;/a&gt;Where do spot instances come from?&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Most of this section is pure speculation. I am presenting a
hypothesis about AWS’s division of instance resources which may be
completely wrong. However as far as I’m concerned it is a hypothesis
that is in line with actual observations.&lt;/p&gt;

&lt;p&gt;The official statement from AWS is that the capacity for spot
instances is &lt;em&gt;“spare Amazon EC2 instances&lt;/em&gt;”
(&lt;a href=&quot;http://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;source&lt;/a&gt;). A
bit more verbose is
&lt;a href=&quot;https://forums.aws.amazon.com/message.jspa?messageID=281838#281838&quot;&gt;Dave@AWS’s commentary&lt;/a&gt;
in the AWS forums:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“To answer your second question, you asked what other capacity
pools could be a part of Spot. Behind the scenes, our goal is to
have all of Amazon EC2’s unused capacity integrated into Spot. By
optimizing the use of these instances, we hope to be able to pass
along more savings over time to our customers. Selling our unused
capacity means we may leverage unused capacity from other pools like
On-Demand or &lt;b&gt;other parts of our capacity that can be temporarily
sold but may need to be reclaimed at a later time&lt;/b&gt;. It would take
precedence over On-Demand, because we do not have the ability to
reclaim On-Demand instances, so they cannot be sold there.”&lt;/em&gt;
(Emphasis is mine.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me go through behaviors associated with the main instance types:&lt;/p&gt;

&lt;figure&gt;
  &lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Instance type&lt;/th&gt;&lt;th&gt;Guaranteed availability&lt;/th&gt;&lt;th&gt;Arbitrary termination&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;On-demand instance&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Reserved instance&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Spot instance&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/figure&gt;

&lt;p&gt;(Notice how reserved instances and spot instances are complementary to
each other.) Although AWS may have other (internal?) capacity pools
with other access constraints, I think that “unused” capacity at any
moment can be divided into two sets: one that can be used for
on-demand instances and one that &lt;strong&gt;cannot&lt;/strong&gt; be used for on-demand
instances. This is because of the semantics of reserved instances.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;“Reserved Instances provide a capacity reservation so that you can
have confidence in your ability to launch the number of instances
you have reserved when you need them.”&lt;/em&gt;
(&lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/reserved-instances/&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you purchase a reserved instance &lt;strong&gt;you have no obligation to run
it&lt;/strong&gt;, but AWS has an obligation to provide you with a reserved
instance any time you &lt;strong&gt;want to run it&lt;/strong&gt;. This means that any reserved
instance that &lt;em&gt;is not running&lt;/em&gt; could be sold, but &lt;em&gt;not&lt;/em&gt; as an
on-demand instance since AWS cannot evict an on-demand instance at
will. See the figure below (which doesn’t have too many non-negations):&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/ec2-capacity-categorized.svg&quot;&gt;&lt;img src=&quot;/assets/posts/ec2-capacity-categorized.svg&quot; alt=&quot;ec2 capacity pools&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;/figure&gt;

&lt;p&gt;At any moment in time AWS’s total capacity is split into running
instances and unused capacity. Running instances are further divided
by type into reserved instances, on-demand instances and spot
intances. The pool of unused capacity has a portion which &lt;strong&gt;cannot&lt;/strong&gt;
be sold as on-demand instances (because if it was sold and a lot of
powered-off reserved instances were started it might not be able to
provision resources for all those reserved instances). Thus &lt;strong&gt;there is
unused capacity that can only be sold as spot instances.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also means that there &lt;strong&gt;can be unused spot instance capacity even
when on-demand instances cannot be provisioned&lt;/strong&gt;. So finally we can
explain why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; instances could be purchased from spot market
even when you couldn’t buy on-demand instances: there was a pool of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; reserved instances already sold that were &lt;strong&gt;not powered
on&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When reserved instances are powered on I think this is what happens:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;If there is unused capacity, it is used to provision the reserved
instance. End of story.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If no unused capacity was available, the spot market is notified
that it needs to release capacity from the spot pool.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Spot market algorithm recalculates the spot price based on the new
(reduced) total capacity. If this changes the spot market price
then it’ll terminate those spot instances whose bid price fell
below the spot market price. The released instance capacity is
allocated back to the reserved instance.&lt;/p&gt;

    &lt;p&gt;What happens if the change of the capacity does not change the spot
price? I’m not sure. It might be that the spot market algorithm
will forcefully increase the spot price. As well it might not. The
exact wording from AWS is &lt;em&gt;“If the Spot price exceeds your max bid
or there is no longer spare EC2 capacity in a given Spot pool, your
instances will be terminated.”&lt;/em&gt; which &lt;em&gt;I think&lt;/em&gt; leaves open the
possibility that a spot instance is terminated also on capacity
decrease even when the bid price doesn’t change.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;If anyone has had their spot instance terminated even when the bid
price equals spot price I’d be delighted to hear about your
experiences.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;(It is possible that there are also &lt;em&gt;other&lt;/em&gt; pools of resources that
are available for spot market use. Maybe new servers are first
assigned to a “burn-in pool” which is sold only via the spot
market. Maybe AWS has internal testing pools that are available for
customers when not needed. I have not seen anything that would suggest
so, though.)&lt;/p&gt;

&lt;h3 id=&quot;market-efficiency-and-reserved-instances&quot;&gt;Market efficiency and reserved instances&lt;/h3&gt;

&lt;p&gt;If my hypothesis about that powered-off reserved instance capacity is
sold in the spot market then (I claim) that spot market is essential
for AWS to maximize its income from reserved instances.&lt;/p&gt;

&lt;p&gt;You could say that &lt;strong&gt;a working spot market is a requirement for
reserved instances&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think about it. If AWS was not able to resell unpowered reserved
instances then it would be making loss with reserved instances. The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.8xlarge&lt;/code&gt; light usage reserved instance upfront cost is $2666. It
has 32 (virtual) cores and 60 GiBs of memory so I think that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.8xlarge&lt;/code&gt; represents almost a physical single server (each
E5-2680v2 has 20 threads, which I guess maps to an EC2 core) and &lt;strong&gt;I’m
pretty sure it’ll cost more than $2666&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If AWS was not reselling unpowered reserved instance capacity then
anyone buying a light utilization reserved instance would most likely
end up costing AWS concrete and real money. At the minimum it would
make the gross margin on those physical servers very low.&lt;/p&gt;

&lt;h3 id=&quot;open-questions&quot;&gt;Open questions&lt;/h3&gt;

&lt;p&gt;I have a hypothesis. Good hypotheses can be tested with tests that
either falsify the hypothesis or give results that are in line with
earlier predictions.&lt;/p&gt;

&lt;p&gt;Actually, to be accurate, I have two hypothesis. The first one is that
&lt;strong&gt;spot market price is affected by supply and demand for all types of
EC2 instances&lt;/strong&gt; (also that there is a minimum spot price and there is
no maximum spot price but we know the first for a fact and I’m not
sure the second one is meaningful to explore at all).&lt;/p&gt;

&lt;p&gt;The second one is that &lt;strong&gt;unused but purchased reserved instance
capacity is re-sold as spot instances&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ll infer from these that the spot market should behave in the
following manner (all of these apply to each region, instance type and
availability zone separately):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Unpowered reserved instances and stopped on-demand instances should
not affect spot price.&lt;/li&gt;
  &lt;li&gt;Purchasing reserved instances (without powering them on) …
    &lt;ul&gt;
      &lt;li&gt;… should not affect spot price.&lt;/li&gt;
      &lt;li&gt;… should decrease unused on-demand instance capacity. (This of
course may not be visible in any way.)&lt;/li&gt;
      &lt;li&gt;… should increase unused spot instance capacity.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Powering reserved instances on …
    &lt;ul&gt;
      &lt;li&gt;… may increase spot price.&lt;/li&gt;
      &lt;li&gt;… may cause spot instances to be terminated (even when spot
price remains unaffected).&lt;/li&gt;
      &lt;li&gt;… should not affect availability of on-demand instances.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Powering reserved instances off …
    &lt;ul&gt;
      &lt;li&gt;may decrease spot price.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Provisioning new on-demand instances or starting stopped on-demand
instances …
    &lt;ul&gt;
      &lt;li&gt;… may increase spot price. (We already know via AWS forum
comments about the $999.99 spot price spike that demand for
on-demand instances can affect spot market prices. It is not
clear what the mechanism here is though — does AWS
preferentially give capacity to on-demand requests?)&lt;/li&gt;
      &lt;li&gt;… may cause spot instances to be terminated. (See previous.)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Terminating on-demand instances or stopping on-demand instances may
decrease spot price.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s a lot. How could these be tested? First and foremost, testing
any of these is potentially &lt;strong&gt;expensive&lt;/strong&gt; as you need to provision
instances and put in bids for spot instances and you’ll need to pay up
for all of that. (These might also violate AWS’s
&lt;a href=&quot;http://aws.amazon.com/aup/&quot;&gt;Acceptable Use Policy&lt;/a&gt;.) It might be
possible to infer some of this data from actual spot market logs
and/or other monitoring data, though how I don’t know.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Buy one or more reserved instances. Start reserved instances. Based
on the hypothetised behavior this should cause the spot market price
to either increase or remain the same.&lt;/p&gt;

    &lt;p&gt;(Given that there are other people powering instances on and off
this would show up only as a statistical result from many
iterations. This applies to all other tests too.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Power off reserved instances. This should cause the spot market
price to decrease or remain the same.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Purchase spot instances at spot market price or slightly above. See
how often their termination is associated with spot price
increases. (Some of them should not be.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Purchase spot instances at spot market price. Power on reserved
instances. There should be a correlation between starting your
reserved instances and termination of your spot instances.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Start on-demand instances. This may be correlated with spot price
increase.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Stop on-demand instances. This may be correlated with spot price
decrease.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course testing any of these is fraught with difficulty. Starting
and stopping one instance is unlikely to affect the spot market price
(the system would have to be near a transition point) and any result
could be swamped badly by random effects (other users). You could
reduce environmental noise by choosing relatively unused region, zone
and instance type but in that case you’d probably have to purchase a
significant number of instances to see &lt;em&gt;any&lt;/em&gt; effect.&lt;/p&gt;

&lt;h3 id=&quot;how-does-this-affect-you&quot;&gt;How does this affect you?&lt;/h3&gt;

&lt;p&gt;Not really much. You shouldn’t try to second-guess future behavior of
spot prices.&lt;/p&gt;

&lt;p&gt;If my hypothesis is correct, then you might want to keep in mind that
the spot market price is affected by events that occur outside the
spot market. That is even an apparently stable market can change
suddenly &lt;em&gt;without any change in the bidding pool&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But you already knew that spot market is volatile, didn’t you? No new
news, then.&lt;/p&gt;

&lt;p&gt;Here’s the &lt;a href=&quot;/2014/03/25/ec2-spot-price-minimum&quot;&gt;next post in the series&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using spot instances</title>
   <link href="http://santtu.iki.fi/2014/03/19/ec2-spot-usage"/>
   <updated>2014-03-19T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/19/ec2-spot-usage</id>
   <content type="html">&lt;p&gt;(You might want first see the &lt;a href=&quot;/2014/03/12/ec2-spot-intro&quot;&gt;introduction to this series of
posts&lt;/a&gt; if you jumped in here
randomly.)&lt;/p&gt;

&lt;h2 id=&quot;how-to-use-spot-instances&quot;&gt;&lt;a name=&quot;si-howto&quot;&gt;&lt;/a&gt;How to use spot instances&lt;/h2&gt;

&lt;p&gt;I’m going through a couple of topics related on &lt;em&gt;how to use spot
instances&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Suitable applications and workloads for spot instances&lt;/li&gt;
  &lt;li&gt;Bidding automation and bidding strategies&lt;/li&gt;
  &lt;li&gt;Minimizing effects of price spikes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Determining whether your application can benefit from cost savings
using spot instance is quite straightforward to analyze — it’s a cost
vs. cost analysis. There is quite a lot of information on bidding
strategies and cost spike mitigation, but information in bidding
automation is sparse as companies using spot instances generally do
not publish their bidding engines or its parameters.&lt;/p&gt;

&lt;h3 id=&quot;suitable-applications-and-workloads&quot;&gt;Suitable applications and workloads&lt;/h3&gt;

&lt;p&gt;Here’s a list of applications suitable for spot instances &lt;a href=&quot;http://www.slideshare.net/AmazonWebServices/optimizing-your-infrastructure-costs-on-aws/22&quot;&gt;according
to the source
itself&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Batch processing&lt;/li&gt;
  &lt;li&gt;Hadoop&lt;/li&gt;
  &lt;li&gt;Scientific computing&lt;/li&gt;
  &lt;li&gt;Video and image processing and rendering&lt;/li&gt;
  &lt;li&gt;Web / Data crawling&lt;/li&gt;
  &lt;li&gt;Financial (analytics)&lt;/li&gt;
  &lt;li&gt;HPC&lt;/li&gt;
  &lt;li&gt;Cheap compute (“backend servers for facebook games”)&lt;/li&gt;
  &lt;li&gt;Testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common theme in all of these is &lt;strong&gt;loss of an instance is not a
catastrophe&lt;/strong&gt;. You can influence the likelihood of an instance loss
through the bid price (see &lt;a href=&quot;/2014/03/12/ec2-spot-instances#si-spot-availability&quot;&gt;instance availability&lt;/a&gt; in previous
post), but unless you are willing to face potentially &lt;a href=&quot;/2014/03/12/ec2-spot-instances#si-spot-999-dollars&quot;&gt;absurd
costs&lt;/a&gt; to guarantee 100% spot instance availability
you’ll have to come to face with the fact that:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You have to be able to recover from sudden spot instance
termination.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you would want to use spot instances and whether you can use
spot instances is determined by three factors:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Potential savings gained by using spot instances.&lt;/li&gt;
  &lt;li&gt;Costs of a spot instance failure. For example loss of profit and
money and work required to recover.&lt;/li&gt;
  &lt;li&gt;Costs required to either completely avoid failure in face of spot
instance failures, or to mitigate the risk to acceptable levels.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The firsts two are recurring (you get savings continuously, but spot
instance failures also occur continuously) whereas the third one is
mostly one-off cost.&lt;/p&gt;

&lt;p&gt;And face it, if you are using spot instances you have to be prepared
that &lt;strong&gt;many of them fail at the same time&lt;/strong&gt;. You can have some
influence over the number of lost instances by using multiple
availability zones and tiered bidding (see
&lt;a href=&quot;http://devblog.moz.com/2011/09/amazon-ec2-spot-request-volatility-hits-1000hour/&quot;&gt;moz.com developer blog for excellent insights&lt;/a&gt;)
but however you slice and dice you still come to the fact that:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You have to be able to recover from sudden spot instance
termination.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How&lt;/strong&gt; you deal with instance termination is affected by what are
your costs to fail and costs to prevent failure. Consider a few cases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Spot instances as build slaves.&lt;/strong&gt; Your CI automatically provisions
build slaves from spot market as needed (and tears them down when
demand goes down). So now suddenly all your build slaves went away —
so what? Jobs failed, builds lost, but it’s not going to kill your
devtest.&lt;/p&gt;

    &lt;p&gt;The recovery method in this case would be simple: first of all, the
CI instance launcher might already have built-in balancing from many
zones (meaning it’ll bid in multiple availability zones). Even if
that wasn’t the case you could go and manually change the bidding
parameters to a higher bid price (maybe you accept a bit higher
costs while thinking of some other solution), use another zone or
use another instance type. You might equally well just wait a while
to see if the price just spiked and would go down soon.&lt;/p&gt;

    &lt;p&gt;In this case it is likely that the cost to prevent interruption of
CI jobs would be higher than productivity losses so it is reasonable
just to wait it out and handle any aftermath manually.&lt;/p&gt;

    &lt;p&gt;(Just do not run your build master in a spot instance.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Hadoop cluster.&lt;/strong&gt; Assuming you are using your Hadoop cluster
semi-continuously (ground radar signal processing, mobile game user
analysis etc.) there are a few possible scenarios. For the most part
Hadoop will automatically re-assign map-reduce jobs from failed
nodes, so loss of some nodes isn’t a biggie for Hadoop at
all. Mahujar’s post &lt;a href=&quot;http://www.qubole.com/riding-the-spotted-elephant/&quot;&gt;Riding the Spotted
Elephant&lt;/a&gt; is an
excellent article discussing various pros and cons on different ways
to use spot instances with Hadoop. Essentially this boils down to:&lt;/p&gt;

    &lt;p&gt;It is possible to run a Hadoop cluster using spot instances where
sudden price peaks will have only a limited effect (delaying
completion of some jobs) sans &lt;em&gt;force majeure&lt;/em&gt; situations.&lt;/p&gt;

    &lt;p&gt;In this case you could be hedging your bets by using a hybrid
cluster, some on-demand instances and some spot instances,
potentially with tiered bidding. This will increase the running cost
but will be highly likely to prevent massive failures.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Financial analysis.&lt;/strong&gt; (I’m not a financial market wiz, so bear
with my unbelievable scenario here, please.) You’re running a
financial modeling job nightly using spot instances. The job will
take 4 hours to complete and the time window to run it is six
hours. It &lt;strong&gt;must not fail&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;Okay, if it must not fail then you should &lt;strong&gt;not&lt;/strong&gt; be running it
using spot instances in the first place. So let’s reword the
requirement. “Must not fail with nightly operating costs less than
X.” That is, if the cost of &lt;em&gt;not failing&lt;/em&gt; would be over X you can
fail.&lt;/p&gt;

    &lt;p&gt;You’ll need three things: bidding automation, provisioning
automation and checkpointing. The first one is to try to keep your
instances alive as much as feasible. The second one is to try to
acquire complementary resources (on-demand instances, other types of
spot instances, another region — whatever it takes) in case you
start losing spot instances and the third one is to ensure that when
you get replacement instances you can quickly continue from where
the analysis stopped without having to re-do everything from
scratch.&lt;/p&gt;

    &lt;p&gt;In this case the cost of prevention is large — setting up the
required automation &lt;em&gt;and testing it to death&lt;/em&gt; will itself require a
large effort, not to speak about the costs that will come &lt;em&gt;after the
automation kicks in&lt;/em&gt;. But then again, the failure to run to
completion would be expensive too.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The less time-critical and more resilient your computing
requirements are the easier it is to move them over to use spot
instances.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you are using AWS in a large scale then you should already have
disaster recovery plans for situations that would affect your
service such as a whole availability zone going out (or a whole
region in case you are
&lt;a href=&quot;http://techblog.netflix.com/2011/04/lessons-netflix-learned-from-aws-outage.html&quot;&gt;Netflix&lt;/a&gt;). When
using spot instances you’ll need to factor in plans for &lt;em&gt;persistent
spot price increases&lt;/em&gt;. If spot prices go up, for how long are you
willing to “wait it out” to see if they drop back down? What will
you then do when you decide they’re not coming down?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Don’t use spot instances if your requirements include “must not fail”&lt;/li&gt;
  &lt;li&gt;Do a cost-benefit analysis:
    &lt;ul&gt;
      &lt;li&gt;Estimate savings&lt;/li&gt;
      &lt;li&gt;Estimate cost of failure&lt;/li&gt;
      &lt;li&gt;Estimate cost of avoiding failure&lt;/li&gt;
      &lt;li&gt;Compare&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;bidding-automation-and-bidding-strategies&quot;&gt;Bidding automation and bidding strategies&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you are using spot instances now and then for one-off tests you
should do bidding manually. In this case you should bid higher than
the current market price (see what I wrote about
&lt;a href=&quot;/2014/03/12/ec2-spot-instances#si-spot-availability&quot;&gt;instance availability&lt;/a&gt; in previous post) to prevent small price
fluctuations from terminating your instance. Just remember — don’t
bid higher than you are willing to pay!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For simple use cases a using auto scaling for provisioning automation
and setting the spot instance bid price (in auto scale launch
configuration) is sufficient. This can’t alone guarantee availability
of a service, but it will be enough for less than 24/7 operations.&lt;/p&gt;

&lt;p&gt;If you had provisioning automation (automatic scale-up and scale-down)
before then adding spot instances brings in a few complications:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Launching spot instances takes a longer time than on-demand
instances (bidding process itself takes extra time).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Spot market price &lt;strike&gt;can&lt;/strike&gt; will vary over time,
including potentially large spikes. You have to decide how to deal
with spikes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Your spot instances can all just &lt;em&gt;vanish&lt;/em&gt; with a sudden spot price
spike.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing a spot market bidding and provisioning engine is thus more
complicated than for scaling up and down with on-demand
instances. &lt;strong&gt;Do make sure&lt;/strong&gt; that you put in hard limits to your bid
prices. Remember the poor sod who paid $999.99/hour for his/her spot
instances.&lt;/p&gt;

&lt;h4 id=&quot;strategies&quot;&gt;Strategies&lt;/h4&gt;

&lt;p&gt;Depending on your application requirements you can apply several
different provisioning and bidding
strategies. &lt;a href=&quot;http://www.youtube.com/watch?v=WD9N73F3Fao&quot;&gt;Here’s a video&lt;/a&gt;
that discusses various strategies AWS has detected its customers
using:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Optimizing costs.&lt;/strong&gt; These customers bid at reserved instance
pricing level with the goal of gaining RI-level costs without their
up-front costs. Needless to say, bidding at this low level you are
facing loss of all spot instances during a price hike.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Optimizing costs and availability.&lt;/strong&gt; These bid at a level between
reserved instance price and on-demand instance price. This will not
protect from sudden price hikes, but will prevent smaller
fluctuations from terminating instances.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Capable of switching to on-demand instances.&lt;/strong&gt; These customers
have provisioning automation that can automatically shift from
bidding for spot instances to provisioning on-demand instances when
it detects that spot prices have increased &amp;gt;1x price level. These
typically bid at on-demand price level or a little higher.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;High bidders for availability.&lt;/strong&gt; For these they are interested in
getting &lt;strong&gt;average&lt;/strong&gt; savings from spot instances, but put a large
value on availability of their spot instances. These will bid
significantly higher than on-demand price.&lt;/p&gt;

    &lt;p&gt;I think this is a reasonable strategy to deploy interrupt-sensitive
application using spot instances &lt;strong&gt;with the caveat&lt;/strong&gt; that you must
be able to later move to cheaper resources (on-demand instances,
reserved instances, other zones, other instance types, other
regions) without service interruption. If you cannot move over,
then permanently bidding high in hope of getting &lt;strong&gt;both&lt;/strong&gt; savings
&lt;strong&gt;and&lt;/strong&gt; availability is gambling, not a strategy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;High bidders for resources.&lt;/strong&gt; There’s another reason to bid
high. At
&lt;a href=&quot;http://www.youtube.com/watch?v=WD9N73F3Fao#t=239&quot;&gt;4:00 in the video&lt;/a&gt;
there’s a description about BrowserMob’s provisioning strategy
where they put a very high value in getting the resources they
need. When BrowserMob’s system determines it needs more capacity,
it’ll first bid at spot market (the video doesn’t say but I’d guess
at on-demand price). If it can’t get resources from the spot
market, it’ll try to acquire an on-demand instance. If that fails,
it’ll start bidding in the spot market at a high level.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that bidding high is a workable strategy only as long as most
&lt;strong&gt;don’t&lt;/strong&gt; bid high.&lt;/p&gt;

&lt;h4 id=&quot;bidding-over-the-on-demand-price&quot;&gt;&lt;a name=&quot;si-spot-over-bidding&quot;&gt;&lt;/a&gt;Bidding over the on-demand price&lt;/h4&gt;

&lt;p&gt;I want to emphasize the following:&lt;/p&gt;

&lt;p&gt;Contrary to a lot of comments in the Internet &lt;strong&gt;bidding over on-demand
price is an entirely rational bidding strategy&lt;/strong&gt; in certain
cases. Consider the two graphs below:&lt;/p&gt;

&lt;figure class=&quot;full&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/spot-price-us-west-1-c1-xlarge.svg&quot;&gt;&lt;img class=&quot;double&quot; src=&quot;/assets/posts/spot-price-us-west-1-c1-xlarge.svg&quot; alt=&quot;c1.xlarge spot price medium volatility across zones in us-east-1&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;/assets/posts/spot-availability-cost-us-west-1-c1-xlarge.svg&quot;&gt;&lt;img class=&quot;double&quot; src=&quot;/assets/posts/spot-availability-cost-us-west-1-c1-xlarge.svg&quot; alt=&quot;c1.xlarge cost at availability in us-west-1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;&lt;code&gt;c1.xlarge&lt;/code&gt; in &lt;code&gt;us-west-1&lt;/code&gt;. Left
graph shows market price where solid line is daily average and lightly
colored boxes are the daily maximum price. Right graph shows what
would have been the total cost to achieve certain availability
target. The light vertical bar is 1/4x on-demand price.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;The table below shows what you would have had to bid (again, this is
&lt;em&gt;post hoc&lt;/em&gt; analysis, you would not have been able to know these values
beforehand) to gain 100% availability &lt;em&gt;and&lt;/em&gt; what it would have &lt;strong&gt;cost
you&lt;/strong&gt; had you bid at the given level.&lt;/p&gt;

&lt;figure&gt;
  &lt;table&gt;
&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Zone&lt;/th&gt;&lt;th&gt;Relative Bid Price&lt;/th&gt;&lt;th&gt;Relative Cost&lt;/th&gt;&lt;th&gt;Availability&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zone 1&lt;/td&gt;
&lt;td&gt;1.293&lt;/td&gt;
&lt;td&gt;0.201&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zone 2&lt;/td&gt;
&lt;td&gt;17.241&lt;/td&gt;
&lt;td&gt;0.267&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zone 3&lt;/td&gt;
&lt;td&gt;17.241&lt;/td&gt;
&lt;td&gt;0.193&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Bid prices and total costs relative to on-demand prices for
&lt;code&gt;c1.xlarge&lt;/code&gt; instances in &lt;code&gt;us-west-1&lt;/code&gt; over the
same time period as with earlier graphs. The cheapest zone ended being
zone 3 with the required bid being &amp;gt;17× on-demand instance price. Yet
the zone with the lowest maximum bid price (zone 1) ended up being more
4% more expensive than zone 3.&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I think this make it clear that &lt;strong&gt;bidding over the on-demand price can
be entirely sensible strategy&lt;/strong&gt; in some cases. It just isn’t a
strategy you should be doing blindly. If you can’t handle
interruptions nor you can move your workload to other zones, other
spot instance types, or on-demand instances and are bidding high, then
you are in a very, very bad place when the price goes up for an
extended period of time.&lt;/p&gt;

&lt;p&gt;To summarize the last point: unless you have good automation that can
shift your workload seamlessly from high-priced spot instances then
you should stick to one of the three first bidding strategies. They at
least have a known failure model (e.g. you lose instances).&lt;/p&gt;

&lt;h3 id=&quot;minimizing-effects-of-price-volatility&quot;&gt;Minimizing effects of price volatility&lt;/h3&gt;

&lt;p&gt;Since spot price volatility is a given, is it then possible to somehow
control the effects of that volatility? The basic approach is to
reduce the probability of that volatility causing problems and
secondarily to limit the impact of any problems encountered.&lt;/p&gt;

&lt;h4 id=&quot;tiered-bidding-and-multiple-zones&quot;&gt;Tiered bidding and multiple zones&lt;/h4&gt;

&lt;p&gt;There are few other tricks noted elsewhere that you can use to
restrict the severity of price hikes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Bid in multiple tiers. Add some randomness to your spot bids. If you
determine that you should bid your resources at X, then bid at X,
X + 5%, X + 10% and X + 15%. This means that if the spot price peaks
at X + 4% then you’d lose only 3/4 of your spot instances. (You can
elaborate this further and match the bidding structure to some
“reasonable” estimates of price volatility based on history
etc. etc.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bid in multiple availability zones, but in different bids. Don’t
blindly use the AWS’s behavior of picking the cheapest zone when you
specify multiple zones in a bid. If you have bid automation, don’t
blindly always bid in the “cheapest” zone either.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If your application can automatically handle new instances
(self-registration, autodiscovery etc.), you can live short price
spikes through with &lt;em&gt;persistent bids&lt;/em&gt;. Persistent bids stay in the
bidding pool and will be filled at any time the spot price is below
the bid price — even if the bid “lost” its instances due to a price
spike.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS allows you to specify multiple availability zones in a single
bid. In this case AWS will pick the cheapest (lowest spot price) zone
&lt;em&gt;at that moment&lt;/em&gt; where the spot request can be fulfilled.&lt;/p&gt;

&lt;p&gt;If you continuously put your instances into the cheapest zone &lt;strong&gt;the
majority of your instances are likely to end up in a single
availability zone&lt;/strong&gt;. Take a loot at the graph below showing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.small&lt;/code&gt;
spot prices in multiple availability zones. There is always a
possibility that a single zone has a long stretch of relative
tranquility and low prices.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/zones-spot-price-us-east-1-m1-small.svg&quot;&gt;&lt;img src=&quot;/assets/posts/zones-spot-price-us-east-1-m1-small.svg&quot; alt=&quot;m1.small instance prices in us-east-1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;&lt;code&gt;m1.small&lt;/code&gt; in &lt;code&gt;us-east-1&lt;/code&gt;. Notice
how zones 1, 2 and 4 have a long history of low prices and low
volatility, yet zones 2 and 4 have sudden spot price level changes.&lt;/p&gt;
  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Yet that tranquility can always end suddenly. I haven’t looked at time
correlations between zone prices, but from a look at the graphs I
think there is sometimes correlation (e.g. if spot price raises in a
zone for an instance type it is likely to go up in another zone), but
similarly sometimes there is no such correlation.&lt;/p&gt;

&lt;p&gt;So you should ensure that your spot instance bids are distributed over
multiple availability zones if that is feasible for your
application. See &lt;a href=&quot;http://moz.com/blog/crawl-outage&quot;&gt;Bryce Howard’s&lt;/a&gt;
commentary on moz.com crawler outage and how it was primarily caused
by placing spot instances in a single availability zone.&lt;/p&gt;

&lt;h4 id=&quot;hybrid&quot;&gt;Hybrid&lt;/h4&gt;

&lt;p&gt;A very common advice is to
&lt;a href=&quot;http://gigaom.com/2011/12/27/how-to-deal-with-amazons-spot-server-price-spikes/&quot;&gt;not run all your infrastructure on spot instances&lt;/a&gt;. This
is a very good advice. It is not always sensible to go after the
highest savings. A good strategy is to use a healthy mix of reserved
instances, on-demand instances and spot instances.&lt;/p&gt;

&lt;h4 id=&quot;keeping-state-checkpointing-job-subdivision&quot;&gt;Keeping state, checkpointing, job subdivision&lt;/h4&gt;

&lt;p&gt;This is a topic I’m not going to go deeply, but the core idea is
simple:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Periodically save the state of whatever your spot instance is doing
(checkpointing) so that if it is terminated, another instance can
continue from the last saved checkpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(&lt;strong&gt;Edit 2015-01-06&lt;/strong&gt;:
&lt;a href=&quot;https://aws.amazon.com/blogs/aws/new-ec2-spot-instance-termination-notices/&quot;&gt;AWS announced&lt;/a&gt;
a two-minute termination notice available via instance metadata. You
still can’t prevent termination, but you do not get a short notice
before it occurs.)&lt;/p&gt;

&lt;p&gt;Extension of this is to store the state continuously, but there are
tons of tradeoff and what’s a good choice depends on your goals and
your applications. Computation tasks that split naturally into
iterations or queueable jobs are easy, those that have gigabytes of
state or require a lot of I/O to store temporary results are more
difficult.&lt;/p&gt;

&lt;p&gt;Keep in mind that AWS will &lt;strong&gt;not charge for a partial hour on spot
instances it terminates&lt;/strong&gt;. This means that you should consider
checkpointing only for long-running jobs and those where job
completion time is an important factor. If your jobs take less than an
hour then a loss of a spot instance will only delay the job, but that
delay won’t cost you anything in instance charges either.&lt;/p&gt;

&lt;p&gt;(You can
&lt;a href=&quot;http://shlomoswidler.com/2011/02/play-chicken-with-spot-instances.html&quot;&gt;play chicken with spot instances&lt;/a&gt;
where after you’re done with the instance you won’t actually terminate
it immediately, but wait to see if AWS does it before the full
hour. Sometimes this gives you the instance-hour for free…)&lt;/p&gt;

&lt;p&gt;There is some research into checkpointing and spot instances. See for
example
&lt;a href=&quot;http://dx.doi.org/10.1109/TSC.2011.44&quot;&gt;Monetary Cost-Aware Checkpointing and Migration on Amazon Cloud Spot Instances&lt;/a&gt;
(Yi, Andrzejak and Kondo, 2012) and
&lt;a href=&quot;http://dx.doi.org/10.1109/AINA.2012.106&quot;&gt;Reliable Provisioning of Spot Instances for Compute-intensive Applications&lt;/a&gt;
(Voorsluys and Buyya, 2012). I’m not myself aware of systems that use
heavy-handed state checkpointing.  There are quite a few that use spot
instances as worker nodes (with &amp;lt;1hour jobs) where the real difficulty
boils more into detecting failures and tuning retry timeouts than
bothering with any form of checkpointing.&lt;/p&gt;

&lt;h3 id=&quot;commentary&quot;&gt;Commentary&lt;/h3&gt;

&lt;p&gt;It is relatively easy to understand the behavior of spot instances &lt;em&gt;in
itself&lt;/em&gt; — &lt;em&gt;Bid &amp;lt; Price ⇒ Terminate&lt;/em&gt;. The difficulty of using spot
instances lies in the fact that it is a market (at least that’s what
we’re led to believe) driven by supply and demand and a lot of
&lt;em&gt;mostly&lt;/em&gt; rational bidders.&lt;/p&gt;

&lt;p&gt;We can know how our spot instances behave when the spot market price
changes. But &lt;strong&gt;we cannot predict the spot market itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means that although you can influence the likelihood of spot
instance termination through bidding strategy, &lt;strong&gt;you still have to be
able to recover from sudden (and massive) spot instance termination.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Did I get &lt;em&gt;that&lt;/em&gt; through?&lt;/p&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Jenkins &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/Amazon+EC2+Plugin&quot;&gt;AWS EC2
Plugin&lt;/a&gt;
has spot instance support since version 1.19. Caveat emptor: I
haven’t used it with spot instances (on-demand only).&lt;/li&gt;
  &lt;li&gt;That said, I know companies which prefer the &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/Swarm+Plugin&quot;&gt;Swarm
plugin&lt;/a&gt;
for node discovery and use custom provisioning scripts. That’s a
roll-your-own path for bidding and provisioning automation, though.&lt;/li&gt;
  &lt;li&gt;See &lt;a href=&quot;http://www.slideshare.net/AmazonWebServices/reinventing-your-innovation-cycle-by-scaling-out-with-spot-instances-cpn207-aws-reinvent-2013&quot;&gt;Tapjoy’s
slides&lt;/a&gt;
on how they’re using Jenkins with spot instances.&lt;/li&gt;
  &lt;li&gt;AWS’s &lt;a href=&quot;http://www.slideshare.net/amazonwebservices/continuous-deploymentpractices&quot;&gt;Continuous Deployment Practices, with Production, Test and
Development Environments Running on
AWS&lt;/a&gt;
set talks about a lot more than spot instances, but see &lt;a href=&quot;http://www.slideshare.net/amazonwebservices/continuous-deploymentpractices/49&quot;&gt;slide
49&lt;/a&gt;
about where to use spot instances vs. other instance types in a more
complex CI environment.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jesse-anderson.com/2012/02/ec2-performance-spot-instance-roi-and-emr-scalability/&quot;&gt;EC2 Performance, Spot Instance ROI and EMR
Scalability&lt;/a&gt;
by Jesse Anderson covers a lot about determining correct instance
types his project, but covers also using spot instances.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://understandbigdata.wordpress.com/2012/12/26/using-spot-instances-in-amazon-emr-without-the-risk-of-losing-the-job/&quot;&gt;Using Spot Instances in Amazon EMR without the risk of losing the
job&lt;/a&gt;
has concrete examples on how to use EMR via command line with spot
instances.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.usenix.org/legacy/event/hotcloud10/tech/full_papers/Chohan.pdf&quot;&gt;See Spot Run: Using Spot Instances for MapReduce
Workflows&lt;/a&gt;
(Chohan et al, 2010) is a good read. It also notes that under some
conditions adding spot instances (that will be terminated) actually
increases Hadoop job completion time and its total cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the &lt;a href=&quot;/2014/03/20/ec2-spot-market&quot;&gt;next post in the series&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Spot instances and price behavior</title>
   <link href="http://santtu.iki.fi/2014/03/12/ec2-spot-instances"/>
   <updated>2014-03-12T14:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/12/ec2-spot-instances</id>
   <content type="html">&lt;p&gt;(You might want first see the &lt;a href=&quot;/2014/03/12/ec2-spot-intro&quot;&gt;introduction to this series of
posts&lt;/a&gt; if you jumped in here
randomly.)&lt;/p&gt;

&lt;h2 id=&quot;spot-instances-and-the-spot-instance-market&quot;&gt;&lt;a name=&quot;si-market&quot;&gt;&lt;/a&gt;Spot instances and the spot instance market&lt;/h2&gt;

&lt;p&gt;I’m covering the basics of what spot instances are (e.g. how they
differ from on-demand and reserved instances), what is the spot price,
what are its characteristics and how the spot price and the bid price
affect availability of spot instances (from bidder’s point of
view). Finally I’m discussing a famous $999.99/hour instance pricing
event.&lt;/p&gt;

&lt;p&gt;A lot of the information in this section can be found in &lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;AWS’s own
spot instance
documentation&lt;/a&gt;. Most
of the graphs have been generated by me using 90 days of spot pricing
data from December 9th 2013 to March 9th 2014.&lt;/p&gt;

&lt;h3 id=&quot;what-are-spot-instances&quot;&gt;What are spot instances?&lt;/h3&gt;

&lt;p&gt;For the purpose of computation, spot instances are like any other
instance type AWS offers. Where they differ is that &lt;strong&gt;you do not have
a complete control on the lifecycle of spot instances&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Spot instances can be terminated by AWS at any time.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;strong&gt;Edit 2015-01-06&lt;/strong&gt;:
&lt;a href=&quot;https://aws.amazon.com/blogs/aws/new-ec2-spot-instance-termination-notices/&quot;&gt;AWS announced&lt;/a&gt;
a two-minute termination notice available via instance metadata. You
still can’t prevent termination, but you do not get a short notice
before it occurs.)&lt;/p&gt;

&lt;p&gt;With on-demand instances (the regular variety) and reserved instances
you get to choose the lifetime of the instance. With spot instances it
is you &lt;strong&gt;and AWS&lt;/strong&gt; who get to terminate the instance. AWS of course
plays by the market rules so any loss of spot instances is not
arbitrary although it may sometimes seem like so (because not all
variables that affect the market are visible).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why would anyone use spot instances then?&lt;/strong&gt; Simple: cost. Spot
instance prices are variable but on average they offer &lt;strong&gt;significantly
lower prices&lt;/strong&gt; than with on-demand prices. With spot instances it is
possible to get same savings as with 3 year heavy usage reserved
instances offer without the up-front costs.&lt;/p&gt;

&lt;p&gt;If you can structure your computing needs around the potential
arbitrary instance loss then you can gain substantial benefits from
using spot instances. AWS’s own marketing material references to
customer cases with 50-60% savings on instance costs.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Spot instance prices cover only EC2 instances. Other
instance-related resources such as network traffic and EBS usage by
the instance is billed at regular rates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Spot instances are functionally equivalent to other types of instances.&lt;/li&gt;
  &lt;li&gt;Spot instances may be terminated at any time by AWS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-is-the-spot-instance-price&quot;&gt;What is the spot instance price?&lt;/h3&gt;

&lt;p&gt;First of all, spot instances are priced &lt;strong&gt;by instance type, by region
and by availability zone in that region&lt;/strong&gt;. This means that spot market
price for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m1.small&lt;/code&gt; differs from zone to zone even within a single
region, not alone between regions.&lt;/p&gt;

&lt;p&gt;Neither is spot instance pricing fixed. It varies over time and is
determined by the &lt;em&gt;AWS spot market&lt;/em&gt;. The market is essentially an
auction where buyers (spot instance users) submit &lt;strong&gt;bids&lt;/strong&gt;. AWS
determines the spot instance price based on these bids and then&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Everyone with a bid higher or equal to the resulting spot instance
price “wins” and gets the instances they requested (or keeps them,
in case they already exist), and&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Winners pay for the &lt;strong&gt;spot instance price&lt;/strong&gt; and not their own bid
(e.g. everyone pays the same value which may be lower than their
bid).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that anyone &lt;strong&gt;losing their bid&lt;/strong&gt; either will not get their
instances or will get their &lt;strong&gt;existing spot instances terminated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Spot market is a continuous auction where the spot instance price is
continuously updated. The update interval may be anything from minutes
to days, depending on the supply of instance capacity and demand for
spot instances.&lt;/p&gt;

&lt;p&gt;You can see spot market price history in the &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-history.html&quot;&gt;AWS management
console&lt;/a&gt;. Here’s
a typical graph you can get:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/posts/spot-instance-price-history-management-console.png&quot; alt=&quot;Sample spot price history graph from AWS management console&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can twiddle the settings in the UI, but you are limited to 90 days
of pricing history.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;Finally for the sake of completeness (but don’t worry, this
won’t part of the quiz) understand that the actual bidding process is
a bit more complicated than saying “I bid for c1.medium at
$0.050”. You can bid for multiple instances, specify validity time for
the bid, zones to bid in, enable persistent bid requests — and of
course you’ll also need to specify all the other parameters needed to
launch an instance (instance type, AMI, disks and so on). Finally you
can put in as many separate bids as you like.&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Spot instance price is variable and is determined continuously by
AWS based on how customers bid for spot instances.&lt;/li&gt;
  &lt;li&gt;Each region, availability zone and instance type is a separate
market for the purpose of pricing.&lt;/li&gt;
  &lt;li&gt;Whether you get or lose spot instances is determined whether your
bid is equal to or larger than the current spot price.&lt;/li&gt;
  &lt;li&gt;You pay only the current spot price regardless of your bid price.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-do-i-actually-buy-spot-instances&quot;&gt;How do I actually buy spot instances?&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-bid-management.html&quot;&gt;RTFM&lt;/a&gt;
or watch &lt;a href=&quot;http://www.youtube.com/watch?v=Py0VInjRSBE&quot;&gt;this video&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;price-volatility&quot;&gt;Price volatility&lt;/h3&gt;

&lt;p&gt;Spot prices are &lt;strong&gt;volatile&lt;/strong&gt; — they go up, they go down, they go
sideways and all at the same time. I’m no economist and can’t give you
an exact definition of volatility, but please take a look at the graphs
shown below:&lt;/p&gt;

&lt;figure class=&quot;full&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/instance-price-volatility-example.svg&quot;&gt;&lt;img class=&quot;double&quot; src=&quot;/assets/posts/instance-price-volatility-example.svg&quot; alt=&quot;c1.medium vs. cc2.8xlarge price volatility differences&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;/assets/posts/zone-price-volatility-example.svg&quot;&gt;&lt;img class=&quot;double&quot; src=&quot;/assets/posts/zone-price-volatility-example.svg&quot; alt=&quot;c1.medium volatility across zones in us-east-1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;
    &lt;p&gt;Examples of price volatility difference between instance
types (on left) and between different availability zones (on
right). Vertical axis is logarithmic, in units of on-demand instance
pricing. Solid lines are daily averages and the translucent blocks
show the daily maximum price. Different colors represent different
availability zones. Faint gray horizontal lines correspond to 4x, 1x
and 1/4x price compared to on-demand instance pricing. Click images
for larger versions.&lt;/p&gt;

  &lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;From these images it should be clear that there are differences in
volatility, minimum and maximum prices, average prices etc. between
instance types (left image) where the overall volatility for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt; is high over the whole data period, but for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc2.8xlarge&lt;/code&gt;
there is a clear and persistent volatility drop on January 8th.&lt;/p&gt;

&lt;p&gt;There can be significant volatility between different availability
zones in the same region (right image) where the price for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt;
has been pretty stable and low in two zones (zones 1 and 2). This
isn’t the case with all of the other zones (3 to 5) where both daily
averages (solid line) &lt;strong&gt;and&lt;/strong&gt; the maximum daily price (lightly colored
blocks in the background) vary massively from day to day.&lt;/p&gt;

&lt;p&gt;Yes, in the graphs above the &lt;strong&gt;daily average prices are over 10x the
on-demand instance pricing on several days&lt;/strong&gt; with spikes even
higher. In the above graphs the weighted average price for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt;
instance in zone 2 is $0.0184 and for zone 3 $0.3174. The regular
on-demand instance price for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt; is $0.145 per
hour. This may give you a WTF moment but see below. I’m going later to
discuss one situation where &lt;a href=&quot;#si-spot-availability&quot;&gt;bidding over the on-demand
price&lt;/a&gt; would have been a reasonable strategy
&lt;em&gt;post hoc&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;AWS assigns a random permutation of availability zones
  for each customer account. In plain English this means that &lt;strong&gt;my&lt;/strong&gt;
  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1a&lt;/code&gt; might be &lt;strong&gt;your&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1d&lt;/code&gt;. It’s a common tripping
  point when comparing metrics related to zones between different
  accounts. This is also why I omit zone labels from the graphs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Prices can both vary widely, up to multiple times the price
of equivalent on-demand instance.&lt;/li&gt;
  &lt;li&gt;Price volatility can vary massively between instance types in the
same region, and between availability zones for the same instance
type in the same region.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;instance-availability-is-determined-by-bid-prices&quot;&gt;&lt;a name=&quot;si-spot-availability&quot;&gt;&lt;/a&gt;Instance availability is determined by bid prices&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: All of the graphs below use &lt;em&gt;post hoc&lt;/em&gt; analysis. The
  theoretical maximums on availability and price savings would be
  possible to achieve &lt;strong&gt;only if you can predict the future!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So far I’ve said that spot instances may be terminated at any time the
spot price goes over your instance bid price. This doesn’t yet tell us
what is the typical &lt;strong&gt;expected&lt;/strong&gt; lifetime (which in turn determines
availability) of an instance based on a particular bid.&lt;/p&gt;

&lt;p&gt;There is research into algorithms to optimize availability
vs. cost. See &lt;a href=&quot;http://dx.doi.org/10.1109/HPCC.2011.46&quot;&gt;Mazucco and Dumas
(2011)&lt;/a&gt;, &lt;a href=&quot;http://dx.doi.org/10.1109/MASCOTS.2010.34&quot;&gt;Andrzejak et al
(2010)&lt;/a&gt;, &lt;a href=&quot;http://dx.doi.org/10.1109/CCGrid.2011.38&quot;&gt;Wee
(2011)&lt;/a&gt; and &lt;a href=&quot;http://dx.doi.org/10.1145/2509413.2509416&quot;&gt;Ben-Yehuda et
al (2013)&lt;/a&gt;. The last one
(Ben-Yehuda et al) is probably the most thorough in considering price
vs. availability tradeoffs. &lt;strong&gt;Be careful&lt;/strong&gt; when interpreting
conclusions from these and other papers as most of them use data prior
to the &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2011/05/26/improved-pricing-control-for-spot-instances-coming-july-1st/&quot;&gt;July 1st 2011 change of spot market pricing
mechanism&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The figure below shows how &lt;strong&gt;achievable availability&lt;/strong&gt; varies with the
normalized bid price for two types of instances and availability
zones. &lt;small&gt;(I’m calculating availability instead of expected
lifetimes just because it’s easier. A value for expected lifetime as
well as number of interruptions versus bid price would be interesting,
though.)&lt;/small&gt;&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/achievable-availability-example.svg&quot;&gt;&lt;img src=&quot;/assets/posts/achievable-availability-example.svg&quot; alt=&quot;Achievable availability for c1.medium and cc2.8xlarge vs. bid price&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;

    &lt;p&gt;Example showing &lt;b&gt;theoretically&lt;/b&gt; achievable availability versus
normalized bid price with &lt;code&gt;c1.medium&lt;/code&gt; and
&lt;code&gt;cc2.8xlarge&lt;/code&gt; in the &lt;code&gt;us-east-1&lt;/code&gt;
region. Vertical lines correspond to 1/4x, 1x and 4x on-demand
instance price.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This shows that sometimes it is possible to get 100% availability at
less than on-demand instance bid price — look at the purple line for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c1.medium&lt;/code&gt; which hits 100% at bid price of 98% × on-demand price and
99.9% availability at bid price of 32% × on-demand price. But wait,
there’s more! Remember that you don’t pay the bid price but the market
price!&lt;/p&gt;

&lt;p&gt;The figure below is otherwise identical to the one above with the
exception that horizontal axis is the relative &lt;strong&gt;total cost&lt;/strong&gt; (… over
the whole data period analyzed — the result over any other random
range of dates will be different).&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/achievable-availability-cost-example.svg&quot;&gt;&lt;img src=&quot;/assets/posts/achievable-availability-cost-example.svg&quot; alt=&quot;Achievable availability for c1.medium and cc2.8xlarge vs. total cost&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;

    &lt;p&gt;Example showing &lt;b&gt;theoretically&lt;/b&gt; achievable availability versus
normalized cost. Note that even when the bid price might have to be
substantially higher than on-demand price to gain 100% availability
the total cost can still be less.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;This shows that even when you’d have to bid for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc2.8xlarge&lt;/code&gt; at about
4× on-demand price to achieve 100% availability, that availability
would have &lt;strong&gt;cost&lt;/strong&gt; you less than 73% of the total on-demand instance
cost (that is, over the 90 days of the sample data).&lt;/p&gt;

&lt;p&gt;Finally, as a bad cost case example see the figure below:&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;a href=&quot;/assets/posts/worst-case-availability-cost-example.svg&quot;&gt;&lt;img src=&quot;/assets/posts/worst-case-availability-cost-example.svg&quot; alt=&quot;Availability vs. total cost c3.2xlarge&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

  &lt;figcaption&gt;

    &lt;p&gt;Availability vs. total cost for &lt;code&gt;c3.2xlarge&lt;/code&gt; in
&lt;code&gt;us-east-1&lt;/code&gt; over the data period. It is not possible to
achieve even 50% availability without paying substantially more than
for equivalent on-demand instance.&lt;/p&gt;

  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;During the time period this data set covers it was not possible to
achieve any level of reliability for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; instances without
paying substantially more than the equivalent cost for an on-demand
instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why would anyone pay &amp;gt;1× rates?&lt;/strong&gt; During this particular time period
there was a shortage of on-demand and reserved &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c3.2xlarge&lt;/code&gt; capacity,
so the only way to get such an instance was to bid high in the spot
market. This is classic supply and demand equation — at the moment
there is very limited supply of this instance type, yet there is
demand and people are willing to pay. (Why there are instances
available in the spot market while not in the on-demand market is a
topic I’ll cover in a later post.)&lt;/p&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Your bid price determines not only whether you get a spot instance
in the first place, but also how long acquired spot instances stay
alive.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;You control your spot instance’s availability through bid
prices.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;instances-at-99999hour&quot;&gt;&lt;a name=&quot;si-spot-999-dollars&quot;&gt;&lt;/a&gt;Instances at $999.99/hour&lt;/h3&gt;

&lt;p&gt;On September 2011 there was a huge price increase in one zone of the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;us-east-1&lt;/code&gt; region for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2.2xlarge&lt;/code&gt; instances where the spot market
price jumped from about $0.44 to $999.99 per hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Someone had put in $999.99 bid&lt;/li&gt;
  &lt;li&gt;Spot instance capacity / demand changed rapidly (Dave@AWS: &lt;em&gt;“an
sudden increase in demand for On-Demand m2.2xlarge instances”&lt;/em&gt;)&lt;/li&gt;
  &lt;li&gt;Some poor sod ended up paying $999.99 per hour for their spot
instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To understand why this could happen, let’s try to imagine what the
situation might have been in the “bidding pool” (the set of bids on
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m2.2xlarge&lt;/code&gt; spot capacity) before the price hike in a quite
artificial setup with only a few bidders and total supply of just five
spot instances:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/posts/999.99-spot-price-event-low-price.svg&quot;&gt;&lt;img src=&quot;/assets/posts/999.99-spot-price-event-low-price.svg&quot; alt=&quot;Before the $999.99 price hike&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One possible bidding scheme is to allocate capacity to bids in
highest-bidder-first with the final spot price being determined by the
lowest winning bid. Thus in this situation the person with $999.99 bid
will still pay $0.200 per hour.&lt;/p&gt;

&lt;p&gt;If this person now needed three more instances at the same bid price,
then the bidding scheme would work like this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/posts/999.99-spot-price-event-high-price.svg&quot;&gt;&lt;img src=&quot;/assets/posts/999.99-spot-price-event-high-price.svg&quot; alt=&quot;Before the $999.99 price hike&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BOOM!&lt;/p&gt;

&lt;p&gt;In reality we don’t know why the bid price rose as &lt;strong&gt;AWS does tell us
how the spot price is determined&lt;/strong&gt;. It is supposed to be based on some
form of auction model, but it might not be. See &lt;a href=&quot;http://dx.doi.org/10.1109/HPCC.2011.46&quot;&gt;Achieving Performance
and Availability Guarantees with Spot Instances&lt;/a&gt; by Mazucco et al
which discusses bidding schemes and server allocation policies that
maximize the &lt;strong&gt;seller’s profit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The best description on how the spot price is determined is &lt;em&gt;“The Spot
Price is set by Amazon EC2, which fluctuates in real-time according to
Spot Instances supply and demand”&lt;/em&gt;
(&lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;source&lt;/a&gt;). Without
AWS disclosing the actual algorithm it is entirely possible that it is
&lt;strong&gt;not&lt;/strong&gt; even remotely following the simple auction model described
above. It could be really out to maximize AWS’s revenue — in the
previous case the algorithm could have realized that at that
particular moment profit would be maximized with the absurd
$999.99/hour spot price! &lt;small&gt;(Though I do think that this behavior
took AWS by surprise too. I think they fell into the theoretical trap
of assuming that people participating in market are all rational
players, where in reality they often are not.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;This is however pure speculation. From a buyer’s perspective the spot
market does work as it statistically does provide cheaper resources
than the on-demand market.&lt;/p&gt;

&lt;p&gt;AWS has since added &lt;a href=&quot;http://www.mailchannels.com/blog/2013/11/aws-puts-a-cap-on-spot-instance-pricing/&quot;&gt;a cap on the bid
price&lt;/a&gt;
(see &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-limits.html&quot;&gt;also
here&lt;/a&gt;),
limiting potential accidents like this. The default cap limit is 4x
the equivalent on-demand instance price, but it can be increased and
clearly has been increased by some bidders (see &lt;a href=&quot;http://localhost:4000/assets/posts/zone-price-volatility-example.svg&quot;&gt;this
graph&lt;/a&gt;
and note how the maximum and average daily prices have been over 4x
several times).&lt;/p&gt;

&lt;p&gt;Regardless of the cap &lt;strong&gt;you should bid only what you are willing to
pay&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For more information on the actual event, please see &lt;a href=&quot;http://devblog.moz.com/2011/09/amazon-ec2-spot-request-volatility-hits-1000hour/&quot;&gt;brandon’s
early
report&lt;/a&gt;
in devblog.moz.com, a later analysis by &lt;a href=&quot;http://gigaom.com/2011/12/27/how-to-deal-with-amazons-spot-server-price-spikes/&quot;&gt;Jonathan Boutelle from
Slideshare&lt;/a&gt;
and &lt;a href=&quot;https://forums.aws.amazon.com/message.jspa?messageID=281838#281838&quot;&gt;Dave@AWS’s responses on the
event&lt;/a&gt;
in the AWS discussion forum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bid only what you can bear.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;/h3&gt;

&lt;p&gt;You can find a ton of resources on AWS spot instances and the spot
instance market on the net. Here are a few web pages, articles and
research papers I’ve found useful:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;AWS’s own landing page on &lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;spot
instances&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Pretty comperhensive &lt;a href=&quot;http://aws.amazon.com/ec2/purchasing-options/spot-instances/spot-tutorials/&quot;&gt;set of
videos&lt;/a&gt;
from AWS on spot instances&lt;/li&gt;
  &lt;li&gt;Slides from &lt;a href=&quot;http://www.slideshare.net/AmazonWebServices/cpn203saving-with-spotfinal-15492709&quot;&gt;Saving with Spot
Instances&lt;/a&gt;
session in re:Invent 2012 (&lt;a href=&quot;http://www.youtube.com/watch?v=zDrLeHlamvY&quot;&gt;here’s the
video&lt;/a&gt; to go with it,
although the slides are more compact)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://dx.doi.org/10.1145/2509413.2509416&quot;&gt;Deconstructing Amazon EC2 Spot Instance
Pricing&lt;/a&gt; by Ben-Yehuda et
al — remember to read epilogue on page 19!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the &lt;a href=&quot;/2014/03/19/ec2-spot-usage&quot;&gt;next post in the series&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Series on AWS spot instances</title>
   <link href="http://santtu.iki.fi/2014/03/12/ec2-spot-intro"/>
   <updated>2014-03-12T13:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/12/ec2-spot-intro</id>
   <content type="html">&lt;p&gt;While pondering about whether and why AWS would retire instance types
(&lt;a href=&quot;/tags.html#instance retirement-ref&quot;&gt;see here&lt;/a&gt;) I started looking
more deeply into the &lt;a href=&quot;https://aws.amazon.com/ec2/purchasing-options/spot-instances/&quot;&gt;spot instance
market&lt;/a&gt;
to see if and what it could potentially tell about instance type
retirement.&lt;/p&gt;

&lt;p&gt;I started writing one post about the topic. Then I realized it had to
be split into two. And into three. So now I have a series of blog
posts about AWS spot instances and the spot instance market.&lt;/p&gt;

&lt;p&gt;I’ve split these posts into the following topics:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/2014/03/12/ec2-spot-instances&quot;&gt;Overview of spot instances and the spot instance market&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2014/03/19/ec2-spot-usage&quot;&gt;How to actually use spot instances&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2014/03/20/ec2-spot-market&quot;&gt;Why spot market exists, where do spot instances come from and what
drives spot instance prices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2014/03/25/ec2-spot-price-minimum&quot;&gt;Interlude into discussion of spot price minimums&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;What can the spot market tell about AWS’s capacity changes (in progress)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most of the information I’m going to present is collected from several
sources which themselves have done excellent research and provide
excellent advise for spot instance users. I’ll try to give credit to
those sources as far as possible without sacrificing readability of
this piece.&lt;/p&gt;

&lt;p&gt;Now, &lt;a href=&quot;/2014/03/12/ec2-spot-instances&quot;&gt;onwards to the first chapter&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>m1 marching into obsolescence?</title>
   <link href="http://santtu.iki.fi/2014/03/07/retiring-instance-types-revisited"/>
   <updated>2014-03-07T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/07/retiring-instance-types-revisited</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;I’m revisiting the topic of my earlier post &lt;a href=&quot;/2014/01/13/aws-retiring-instance-types&quot;&gt;retiring instance
types&lt;/a&gt; from a
couple months back. You might want to check it out first. It has
more pictures than this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ars technica wrote about &lt;a href=&quot;http://arstechnica.com/information-technology/2014/01/intel-inside-shifts-from-pcs-to-virtual-machines-in-the-cloud/&quot;&gt;Intel’s “Powered by Intel Cloud
Technology”&lt;/a&gt;
just two days after my previous AWS post. I couldn’t find a date when
&lt;a href=&quot;http://www.intelcloudfinder.com/intelcloudtechnology&quot;&gt;this branding
program&lt;/a&gt; was
launched, but the Ars post was the earliest I could find (Intel’s blog
has a post from &lt;a href=&quot;https://communities.intel.com/community/itpeernetwork/datastack/blog/2014/01/15/looking-for-the-right-cloud-technology-look-for-the-new-intel-badge&quot;&gt;January
15th&lt;/a&gt;)
so I’m assuming this really was announced in January.&lt;/p&gt;

&lt;p&gt;It is clear that AWS and Intel have been working together on this
programme for a longer time. It is telling that no AWS announcement
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2012/&quot;&gt;on year 2012&lt;/a&gt; is
more explicit about processor type than “Intel Xeon”, no announcement
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2011/&quot;&gt;from year 2011&lt;/a&gt;
mentions processor type at all but &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2013/&quot;&gt;year
2013&lt;/a&gt; starts right
off the bat with the announcement of the &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2013/01/21/announcing-high-mem-cluster-instances-for-amazon-ec2/&quot;&gt;cr1 instance
class&lt;/a&gt;
giving a full lowdown on its processor specs.&lt;/p&gt;

&lt;p&gt;There was an Intel PR announcement on &lt;a href=&quot;http://newsroom.intel.com/community/intel_newsroom/blog/2013/09/10/intel-introduces-highly-versatile-datacenter-processor-family-architected-for-new-era-of-services&quot;&gt;September 10th
2013&lt;/a&gt;
about AWS’s use of Intel processors but &lt;strong&gt;that story&lt;/strong&gt; does not
contain reference to the “Powered by Intel Cloud Technology”
program. So something was brewing already in September 2013 but it
wasn’t yet given a name …&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So it seems that the reason behind AWS becoming more explicit about
  the underlying processor hardware is due to its relationships with
  Intel and the “Powered by Intel Cloud Technology” program. I just
  wonder what kind of benefits this program gives AWS — and as &lt;a href=&quot;http://arstechnica.com/information-technology/2014/01/intel-inside-shifts-from-pcs-to-virtual-machines-in-the-cloud/&quot;&gt;Ars
  points
  out&lt;/a&gt;,
  why neither Compute Engine or Windows Azure partake in the program?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you trawl the Internet archives you’ll also find that AWS &lt;strong&gt;did
not&lt;/strong&gt; specify m3’s processor type when they were &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2012/10/31/announcing-amazon-ec2-m3-instances-and-m1-price-drop/&quot;&gt;first
announced&lt;/a&gt;. The
exact processor type was added to EC2 instance description sometime
between &lt;a href=&quot;http://web.archive.org/web/20130901044833/https://aws.amazon.com/ec2/instance-types/&quot;&gt;September 1st
2013&lt;/a&gt;
and &lt;a href=&quot;http://web.archive.org/web/20130909200405/http://aws.amazon.com/ec2/instance-types/&quot;&gt;September 9th
2013&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Okay but how does this buhaha about “Intel Inside” and m3 have to do with m1?&lt;/p&gt;

&lt;p&gt;AWS has given a lot of screen estate telling its customers how m3
instance types are cheaper and better and shinier than the old
first-generation m1 instances. For example, see the announcement on
&lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2014/01/21/announcing-new-amazon-ec2-m3-instance-sizes-and-lower-prices-for-amazon-s3-and-amazon-ebs/&quot;&gt;m3.medium and m3.large
types&lt;/a&gt;
and &lt;a href=&quot;http://aws.amazon.com/about-aws/whats-new/2014/02/20/amazon-rds-now-offers-new-faster-and-cheaper-db-instances/&quot;&gt;availability of m3 RDS
instances&lt;/a&gt;
for a few choice words. Alternatively hear what AWS’s chief
evangelist, &lt;a href=&quot;http://aws.typepad.com/aws/2014/02/amazon-rds-support-for-second-generation-standard-instances.html&quot;&gt;Jeff Barr
says&lt;/a&gt;:
&lt;em&gt;“You get significantly higher and more consistent compute power at a
lower price when you use these instances”&lt;/em&gt;. Or &lt;em&gt;“compared to M1
instances, M3 instances provide better, more consistent perfromance at
lower prices”&lt;/em&gt; on the &lt;a href=&quot;http://aws.amazon.com/ec2/instance-types/&quot;&gt;EC2 instance description page
itself&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For me this seems like less-than-subtle prodding for AWS customers to
move away from m1 EC2 and RDS instance types. But why? Moving your
customers to a &lt;strong&gt;cheaper&lt;/strong&gt; platform makes no business sense &lt;strong&gt;unless
it generates more revenue&lt;/strong&gt; than is lost due to lower pricing. How
could this be true? A couple of possibilities exist:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;New instance classes are cheaper to purchase and/or operate (cheap
enough to give better operating profit than old instances). Note
that the newer instance types fall under Intel’s cloud technology
program whereas old ones do not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There is a desire to obsolete old instance class for some &lt;strong&gt;other&lt;/strong&gt;
reason than operating profit alone. (Maybe AWS wants those racks
freed for other uses?)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following the business logic of the first case will still eventually
lead to obsoletion of old instance class &lt;strong&gt;hardware&lt;/strong&gt;. Whether it will
lead to obsoletion of the instance &lt;strong&gt;class&lt;/strong&gt; is another thing
entirely. Yet it is hard to see how the “old” m1 instance class could
be kept interesting to customers without reducing its price. But why
do that? The only reason would be to squeeze the last cents out of
EOL’ed class.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Of course AWS has the &lt;strong&gt;spot market&lt;/strong&gt; to peddle those less
desirable instance types at so-called “market rates” … More on the
spot market later.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Now for the practical advise section! Now after m3.medium was
announced it is clear that you should:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Use m3.medium instead of m1.medium.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use m3.large instead of m1.large.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Use m3.xlarge instead of m1.xlarge.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using any other m1 type than m1.small you really really
should go and evaluate m3 class instances instead. They offer better
performance at lower cost. (Just don’t do it blindly. Test
first. Never assume anything with instances. Trust your own numbers,
not others’.)&lt;/p&gt;

&lt;p&gt;Which makes me ponder, what of m1.small? I earlier argued that
m1.small fills an important sweet price spot between t1.micro and the
next type up the line (at that time either m1.large or c1.medium, now
to m3.medium). This still applies. There is &lt;strong&gt;no&lt;/strong&gt; m3.small.&lt;/p&gt;

&lt;p&gt;At least not yet.&lt;/p&gt;

&lt;p&gt;I wonder.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sockets and concurrency the buggy way</title>
   <link href="http://santtu.iki.fi/2014/03/06/network-and-parallelism-in-erlang"/>
   <updated>2014-03-06T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/06/network-and-parallelism-in-erlang</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Updated 2016-02-16: I have added more details pointing out the exact
conditions under which the race condition I describe can be
triggered. See below.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ll once again share a small gotcha moment from recent programming
experiences. This comes from my jab at &lt;a href=&quot;/2014/03/03/experiences-in-erlang&quot;&gt;Erlang programming&lt;/a&gt; and concerns about a
&lt;em&gt;very&lt;/em&gt; subtle bug I introduced into the hypercube node code I was
writing.&lt;/p&gt;

&lt;p&gt;With subtle I do mean &lt;em&gt;subtle&lt;/em&gt;. It took a specific set of conditions
to manifest the bug. It had a tiny time window at system startup where
it could be triggered and never again after that. I finally could
reproduce the bug somewhat reliably by starting a total of 1024 node
processes in less than 1/4 second, in parallel, in multiple 16-core
physical servers— and even then it showed up in only for one or two
network connections out of 10240 connections that were created during
the system initialization.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As most bugs go, this is obvious once you realize the underlying
problem. For long-time Erlang programmers this might be a known
problem and avoided without a second thought.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;what-i-tried-to-do&quot;&gt;What I tried to do&lt;/h2&gt;

&lt;p&gt;So I’m writing this post hopefully help anyone who might run the same
problem. But before delving into the actual bug let me first tell what
I was trying to do:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I wanted to have a server listening on a port, where&lt;/li&gt;
  &lt;li&gt;Each new connection would be handled by a spawned Erlang process
(e.g. in a separate thread)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are two ways to process incoming traffic on a socket in Erlang:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gen_tcp:recv&lt;/code&gt; in a loop to receive input, then process it. This
is the typical approach taken to network programming in
    &lt;strike&gt;most&lt;/strike&gt;
    &lt;p&gt;all languages.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Use Erlang’s (unique?) method of &lt;strong&gt;active sockets&lt;/strong&gt; where the Erlang
runtime will send incoming network traffic to as messages to the
socket’s controlling process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;I decided to use the latter method.&lt;/strong&gt; It fits nicely into Erlang’s
view of the world where asynchronous interactions occur via
messaging. It also allows nice integration with other processes since
you can handle &lt;strong&gt;both&lt;/strong&gt; Erlang-world messages and non-Erlang-world
interactions in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt; loop.&lt;/p&gt;

&lt;h3 id=&quot;using-an-active-socket-in-a-network-client&quot;&gt;Using an active socket in a network client&lt;/h3&gt;

&lt;p&gt;Here’s an example Erlang program to connect to port 12345 on
localhost, reading data from the socket and printing it out:&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,_}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;localhost&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12345&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			     &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;receive&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,_,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Received: ~ts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
	    &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error or socket closed, exiting.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;~n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	    &lt;span class=&quot;nf&quot;&gt;halt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To try this out, put this into a file and, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo hello | nc -l
12345&lt;/code&gt; in another terminal and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;escript&lt;/code&gt; to run the script. Of
course you need an &lt;a href=&quot;http://www.erlang.org/download.html&quot;&gt;Erlang
installation&lt;/a&gt; in the first place.&lt;/p&gt;

&lt;p&gt;The program opens a connection with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, true}&lt;/code&gt; socket
option. This sets the connected socket into active mode. Incoming data
is then processed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt; which keeps calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive&lt;/code&gt; in a loop
until the socket is closed (or an error occurs).&lt;/p&gt;

&lt;h3 id=&quot;using-active-sockets-in-a-network-server&quot;&gt;Using active sockets in a network server&lt;/h3&gt;

&lt;p&gt;A socket server with active sockets is also straightforward (&lt;strong&gt;except
don’t use this code, see below&lt;/strong&gt;):&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;%% WARNING: Don't use this code, it contains a race condition. See below.
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12345&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;controlling_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;inet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setopts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}]),&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;receive&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,_,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;~w&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; Received: ~ts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
	    &lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;~w&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; Error or socket closed, closing.&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;~n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]),&lt;/span&gt;
	    &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This program will bind to port 12345, accept connections on the port,
spawn an Erlang process for each connection which in turn will echo
all traffic back to the originating socket. Test it out with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo
hello | nc 12345&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You might be wondering about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gen_tcp:controlling_process&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active,
false}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, once}&lt;/code&gt; in the code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;When a socket is in &lt;em&gt;active mode&lt;/em&gt; it will send packets to the
&lt;strong&gt;controlling process&lt;/strong&gt; which is initially the process that created
the socket. Thus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server_loop&lt;/code&gt; must explicitly give control of the
socket to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection_loop&lt;/code&gt; process.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Similarly we don’t want the server process to receive any packets,
which is why the listen socket is defined as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, false}&lt;/code&gt; —
this setting is inherited to the accepted socket so it will also
start in inactive mode.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Finally, the connection handler sets the socket &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, once}&lt;/code&gt;
which is mostly similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, true}&lt;/code&gt; except it adds flow
control to the mix. Which is a good thing before trying to drink
from a fire hose …&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;but-it-has-a-race-condition&quot;&gt;But it has a race condition!&lt;/h3&gt;

&lt;p&gt;If you were not dozing off you’ve realized that &lt;strong&gt;this version has the
race condition&lt;/strong&gt; I mentioned earlier. The race occurs when code is
executed in a particular sequence and the client is sending data at
just the right moment.&lt;/p&gt;

&lt;p&gt;Below is a figure showing two possible sequences of events within the
code, on the left is a sequence with &lt;strong&gt;the desired (working) outcome&lt;/strong&gt;
and on the right side is another but possible &lt;strong&gt;sequence which doesn’t
work&lt;/strong&gt; (there are a few more “bad” execution sequences, but I’ll use
just one as an example):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/erlang-socket-sequence.svg&quot; alt=&quot;Two possible execution paths in the sample server code&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the figure &lt;span style=&quot;background: #ff9da6; padding: 0 0.2em;&quot;&gt;red&lt;/span&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server_loop&lt;/code&gt; code, &lt;span style=&quot;background: #42ff7e; padding: 0 0.2em;&quot;&gt;green&lt;/span&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection_loop&lt;/code&gt; code and
&lt;span style=&quot;background: #71beff; padding: 0 0.2em;&quot;&gt;blue&lt;/span&gt; is
Erlang’s internal-ish network-ish code handling incoming data for active sockets.&lt;/p&gt;

&lt;p&gt;What we want is that the connection handler (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection_loop&lt;/code&gt;) will
receive all data that is sent to the connected socket. Just like
happens in the left sequence — data is received on the socket after
socket’s ownership has changed and the handler code is ready to
receive data.&lt;/p&gt;

&lt;p&gt;On the “bad” sequence the child process will set the socket to active
state &lt;strong&gt;before the parent process has changed the socket’s
ownership&lt;/strong&gt;. This means that any data received on the socket before
ownership change is &lt;strong&gt;sent to the wrong process&lt;/strong&gt;. The recipient will
be the listener process and not process running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection_loop&lt;/code&gt;
code. Oh boy, the data is now lost. &lt;small&gt;(Technically it’s not
lost. It is just unread in the message queue of the wrong
process. Regardless, it is never read.)&lt;/small&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I wrote &lt;a href=&quot;/2014/03/03/experiences-in-erlang&quot;&gt;in the previous post&lt;/a&gt; &lt;em&gt;“[Erlang’s] shared-nothing
process model removes most problems with shared resources.”&lt;/em&gt;
Yep. Erlang removes most race conditions on shared resources by
&lt;strong&gt;eliminating most shared resources&lt;/strong&gt;. When resources &lt;strong&gt;are&lt;/strong&gt; shared
such as on-disk files or &lt;em&gt;network sockets&lt;/em&gt; there can still be
concurrency problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this would be a real server process with request-response protocol
and client-initiated handshake, then the connection would also be
stuck permanently (server never sees the handshake, yet client has
successfully sent it and is expecting a reply).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I want to emphasize how difficult this bug is to trigger. The remote
client will not be sending data until the TCP handshake
completes. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen&lt;/code&gt; returns, the TCP stack has already sent a
SYN-ACK packet to the client. After it reaches the client it can
start sending data, but this will take with any Internet connection
anything from a few milliseconds to hundreds of milliseconds.&lt;/p&gt;

  &lt;p&gt;I instrumented the code, showing that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server_loop&lt;/code&gt; took (on a
MacBook) on average 103 µs (99.9% percentile was 170 µs — these are
microseconds e.g. 1/1000th of a millisecond) to spawn a process and
hand the controlling socket over. Thus unless the server is
massively overloaded it is nigh-on impossible to trigger the bug
over the Internet and difficult even on a local network (the network
I used has ~150 µs average packet latency).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The next few paragraphs were added on 2016-02-16. My thanks to
Robert Gionea for pointing out the distinction between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active,
true}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{active, once}&lt;/code&gt; in how parent process queue is handled.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Robert’s email got me looking much more closely on the bug and digging
deep into Erlang runtime’s internals which means I can now give out
the exact conditions what cause the bug to occur — there are two
conditions that need to hold so that the code above may lose a packet
due to a race condition:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SMP is enabled (enabled automatically on multicore/multiprocessor
systems).&lt;/li&gt;
  &lt;li&gt;Child process modifies socket’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; state &lt;strong&gt;while&lt;/strong&gt; socket’s
ownership is being transferred (parent calls
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gen_tcp:controlling_process&lt;/code&gt;.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See &lt;a href=&quot;http://bugs.erlang.org/browse/ERL-90&quot;&gt;ERL-90&lt;/a&gt; bug report for
much, much more in-depth description of the actual underlying
problem - it has surprisingly old roots, probably being the side
effect of introduction of SMP capability introducing a new failure
mode to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gen_tcp:controlling_process&lt;/code&gt; that was not fully appreciated
at that time. The fix discussed below prevents the second condition
from happening and thus also prevents the race condition from
occurring.&lt;/p&gt;

&lt;p&gt;(End of 2016-02-16 edit.)&lt;/p&gt;

&lt;h3 id=&quot;de-bugged-versions-of-the-server-code&quot;&gt;De-bugged versions of the server code&lt;/h3&gt;

&lt;p&gt;Fixing this is easy once the problem is identified: just add a
synchronization barrier to ensure that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;connection_loop&lt;/code&gt; won’t be
called until the parent process has relinquished its control on the
socket:&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;%% Version spawning off a process to handle the connection.
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;receive&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;controlling_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Pid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Pid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since this race condition occurs only when &lt;strong&gt;not&lt;/strong&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recv&lt;/code&gt; and
&lt;strong&gt;switching controlling process&lt;/strong&gt; there are also two other ways to
write the code so the race condition never occurs. First one is to
eliminate the need to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;controlling_process&lt;/code&gt; by spawning a new
process for the listener instead:&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;%% Version using the current process to handle the connection, passing socket
%% listening to a spawned process instead.
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and the other is to &lt;strong&gt;not&lt;/strong&gt; use active sockets at all:&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;%% Version eliminating active sockets completely using gen_tcp:recv only.
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;server_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;connection_loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;gen_tcp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;...;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;concurrency-&quot;&gt;&lt;a name=&quot;concurrency&quot;&gt;&lt;/a&gt;Concurrency …&lt;/h3&gt;

&lt;p&gt;This should be a reminder that &lt;strong&gt;concurrency is hard&lt;/strong&gt;. (If you don’t
believe me, check what &lt;a href=&quot;http://en.wikipedia.org/wiki/Simon_Peyton_Jones&quot;&gt;Simon Peyton
Jones&lt;/a&gt; says about
&lt;a href=&quot;http://research.microsoft.com/en-us/um/people/simonpj/papers/stm/STM-OSCON.pdf&quot;&gt;what’s wrong with
locks&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;I have programmed in concurrent environments for decades and I do
consider myself to be highly skilled in concurrent and parallel
programming (multi-thread, multi-process and multi-machine all
alike). (And yet I still fail.) Over my programming history I’ve seen
that almost all novice programmers and even most senior programmers
&lt;strong&gt;1)&lt;/strong&gt; try to avoid using concurrency in the first place, &lt;strong&gt;2)&lt;/strong&gt; not
realizing when they’ve accidentally created concurrent systems and
finally &lt;strong&gt;3)&lt;/strong&gt; when having to face concurrency they often get
synchronization and sequencing wrong (leading to hard-to-find bugs).&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/parallel-rail-tracks.jpg&quot; alt=&quot;Parallel railroad tracks&quot; /&gt;&lt;/p&gt;
  &lt;figcaption&gt;
    &lt;p&gt;Parallel tracks. Get it? Parallel - parallelism? I know, I know … (Image source: &lt;a href=&quot;http://www.flickr.com/photos/callmewhatever/9552127269/&quot;&gt;Daniel Zimmermann&lt;/a&gt;)&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;I think this makes for a very good case to &lt;strong&gt;prefer systems which
provide better and safer concurrency programming models&lt;/strong&gt;. This way at
least the most common concurrency problems get eliminated entirely by
design.&lt;/p&gt;

&lt;p&gt;In modern hyperthreaded multi-core computer architectures the ability
to use multiple cores efficiently is a key to high-performance and/or
responsive applications and services. In scalable architectures
concurrency also is an important tool and similarly a problem (though
it comes in different guise through Brewer’s theorem).&lt;/p&gt;

&lt;p&gt;Yet performance or parallelism should not be gained at the cost of
&lt;strong&gt;correctness&lt;/strong&gt;. For this reason I think that the approach to
concurrency and parallelism taken by most languages is unproductive —
where the programmer is given low-level primitives (threading,
mutexes) and then left to sort the rest by themselves. There should be
much better support.&lt;/p&gt;

&lt;p&gt;To see some examples of how concurrency and parallelism can be made
simpler for programmers see &lt;a href=&quot;http://donsbot.wordpress.com/2010/06/01/open-source-bridge-talk-multicore-haskell-now/&quot;&gt;a presentation on multicore
Haskell&lt;/a&gt;,
Learn you some Erlang’s &lt;a href=&quot;http://learnyousomeerlang.com/the-hitchhikers-guide-to-concurrency&quot;&gt;section on
concurrency&lt;/a&gt;
or introduction to Clojure’s &lt;a href=&quot;http://www.youtube.com/watch?v=dGVqrGmwOAw&quot;&gt;concurrency and STM
mechanisms&lt;/a&gt;
(&lt;a href=&quot;https://github.com/dimhold/clojure-concurrency-rich-hickey/blob/master/ClojureConcurrencyTalk.pdf?raw=true&quot;&gt;slides&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I don’t think concurrency is never going to be easy, but let’s at
least try to figuratively default to giving new programmers a bicycle
instead of an unicycle?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Experiences in Erlang</title>
   <link href="http://santtu.iki.fi/2014/03/03/experiences-in-erlang"/>
   <updated>2014-03-03T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/03/03/experiences-in-erlang</id>
   <content type="html">&lt;p&gt;I got an programming assignment in a course I was taking. The task was
to create an overlay network topology and implement a routing protocol
for it with some given constraints — where I quickly realized a
hypercube mesh would meet the rating criteria. (This shows my age —
hypercube networks were a hot topic in the 90’s. They were used in
supercomputers such as the &lt;a href=&quot;http://en.wikipedia.org/wiki/Connection_Machine&quot;&gt;CM-5&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Unfortunately a binary N-cube routing algorithm is &lt;strong&gt;pretty much
trivial&lt;/strong&gt;. Here’s the whole routing algorithm written in Erlang:&lt;/p&gt;

&lt;div class=&quot;language-erlang highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;find_route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(_,_,[],_)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noroute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;find_route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;band&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Dst&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;band&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;find_route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;bsr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Dst&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;bsr&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Routes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That’s it. 8 lines of code. The first function could be omitted
(deducting two lines) as it guaranteed to be never called. (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Id&lt;/code&gt; is
this node’s address and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dst&lt;/code&gt; is destination address, each element in
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Routes&lt;/code&gt; list is a neighbor in the matching dimension.)&lt;/p&gt;

&lt;p&gt;Since the actual &lt;em&gt;network problem&lt;/em&gt; became trivial you can see why I
picked up Erlang. It was for the sole purpose of &lt;strong&gt;making the
assignment more interesting&lt;/strong&gt;. I had not previously used Erlang — I
was familiar with the syntax and could &lt;em&gt;read&lt;/em&gt; Erlang programs — but
all the libraries, conventions etc. were new to me. I knew of Erlang’s
approach to distributed computing and parallelism and wanted to give
it a spin.&lt;/p&gt;

&lt;p&gt;So, what I learned? I’ll first summarize its pros and cons from my
viewpoint and later elaborate on these:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Pros&lt;/th&gt;&lt;th&gt;Cons&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Language and core libraries are compact, consistent and mature&lt;/li&gt;
&lt;li&gt;Built-in concurrency and messaging&lt;/li&gt;
&lt;li&gt;Pattern matching&lt;/li&gt;
&lt;li&gt;Symbols are always sexy&lt;/li&gt;
&lt;li&gt;Registered processes&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Cryptic compile-time and runtime errors&lt;/li&gt;
&lt;li&gt;Package management&lt;/li&gt;
&lt;li&gt;Structured data ~ painful syntax&lt;/li&gt;
&lt;li&gt;No hierarchical namespaces&lt;/li&gt;
&lt;li&gt;Registered processes&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;The overall result for me is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Erlang is a very nice language, it has great features and I’d love
to use it again.&lt;/li&gt;
  &lt;li&gt;… but it won’t become my default go-to language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Please note&lt;/strong&gt; that I’m basing this post on my experiences. I might
have missed or misinterpreted things that are obvious to other people,
so don’t take this post as any kind of gospel truth of Erlang.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Now the long version. Erlang is really nice in several aspects:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The language is compact and consistent and the standard libraries
are mature (e.g. well documented and debugged). There’s also a good
variety of non-core libraries available which I didn’t have any
trouble of using.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Its built-in support for massive concurrency and distributed
messaging are just manna from heavens.&lt;/p&gt;

    &lt;p&gt;Erlang’s lightweight process model just kicks ass. I’ve spawned 15k
Erlang processes (e.g. threads) without problems whereas in Python
1000 threads? Forget it (you’ll hit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxproc&lt;/code&gt; limit). 99.99% of
the time parallelism is a tool to achieve asynchronous behavior so
that case should be as least limiting as possible. Like Erlang does
(it runs green threads on multiple native threads, getting the best
of both worlds).&lt;/p&gt;

    &lt;p&gt;Also the shared-nothing process model removes most problems with
shared resources. It does make some things more cumbersome and less
efficient, but hey, I’m quite willing to trade a little inefficiency
to programming with a massively less error-prone concurrency model.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pattern matching in functions, assignment and conditionals is
sinfully easy. Don’t care to handle errors, but still want the
process to fail when they occur? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ok,Result} =
maybe_failing_function()&lt;/code&gt; — if the function &lt;em&gt;does not&lt;/em&gt; return
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ok,_}&lt;/code&gt; the runtime will signal that as an error. And of course
&lt;em&gt;guards&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Symbols are always a good thing. Scheme, Ruby and Erlang (among
others) do this right. Oh Python, when will you realize symbols are
a very useful first-class citizen?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Registered processes. They are very useful when they fit the need,
but see below when they &lt;em&gt;don’t&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the minus side there are a few things that will mean that Erlang
won’t be my choice as a default go-to language in the future:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Compiler and runtime errors. So I forgot to make the variable
uppercase and now it thinks I want to do pattern matching with a
symbol? My bad. But you just should give a less cryptic error
message about it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Package management. &lt;a href=&quot;https://github.com/rebar/rebar&quot;&gt;Rebar&lt;/a&gt; can pull
dependencies automatically, but there’s still a world of difference
between writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyYAML&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.py&lt;/code&gt; vs. writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{jiffy,
&quot;0\.8\.5&quot;, {git, &quot;https://github.com/davisp/jiffy&quot;, {tag,
&quot;0.8.5&quot;}}}&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rebar.config&lt;/code&gt; &lt;em&gt;over and over again&lt;/em&gt;. This is not a
problem for large projects where dependency setup is one-time-only
affair, but when doing smaller or one-off programming jobs it would
add up quickly to the workload.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Horrendous syntax for structured data. Changing a field? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NewStruct
= Struct#struct{value=Struct#struct.value + 1}&lt;/code&gt; A little syntatic
sugar here would do miracles. Yes, you can use parse transformations
to help. But that then gets you into another problem of having to
&lt;em&gt;first&lt;/em&gt; get those parse transforms (see previous) and &lt;em&gt;second&lt;/em&gt; to
apply them.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Registered processes. These are nice, I would very much want to use
them but can’t. The idea is that you can register processes by name,
say identify the router process as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;router&lt;/code&gt; and use it directly in
messaging like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;router ! {route,Packet}&lt;/code&gt;. Add a supervisor which
will re-spawn a failed router thread you’ve got a model where you
always know how to reach a working “router” process.&lt;/p&gt;

    &lt;p&gt;Except registered processes are global. I needed to run multiple
hypercube nodes in a single server process, with &lt;em&gt;each&lt;/em&gt; having a
&lt;em&gt;separate&lt;/em&gt; router and &lt;em&gt;separate&lt;/em&gt; local message handler and
&lt;em&gt;separate&lt;/em&gt; remote connectors and &lt;em&gt;separate&lt;/em&gt; state manager.&lt;/p&gt;

    &lt;p&gt;I think this is due to the history of Erlang. It was designed to run
in a loosely coupled but purpose-designed system (telco
exchanges). In that context it made perfect sense to have a globally
identified process. After all, there was only a single system, so
why there would be any need for multiples of any single process?&lt;/p&gt;

    &lt;p&gt;Which does not work in a multitenancy scenario where you have
multiple “domains” of processes, where intra-domain visibility is a
good thing but inter-domain visibility is verboten.&lt;/p&gt;

    &lt;p&gt;So I was stuck to using the process dictionary and lugging process
identifiers around in function arguments.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Lack of hierarchical namespaces. It is two levels and only two
levels. Module and function name and that’s it. So when your
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frobnizer&lt;/code&gt; app needs to have internal module, it is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frobnizer_internal_module&lt;/code&gt; and not
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frobnizer.internal.module&lt;/code&gt;. Module hierarchy and scoping isn’t
&lt;a href=&quot;http://stackoverflow.com/questions/4503131/why-arent-erlang-packages-used&quot;&gt;only syntatic
sugar&lt;/a&gt;
regardless what hard-core erlangistas say. I personally have found
module hierarchy and its close ally, scoping rules a useful feature
in other languages. So why not here? I don’t understand the
opposition for such &lt;a href=&quot;http://www.erlang.se/workshop/2002/Carlsson.pdf&quot;&gt;a simple and
non-intrusive&lt;/a&gt;
change.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I love Erlang’s pragmatic approach to functional programming,
contrasted with Haskell for example, which as a language I simply
admire but
Always. Find. It. Painful. To. Do. Anything. Useful. Using. It. We
don’t write programs (at least mostly) for the pleasure of seeing
beautiful and pure programs. We write programs to get things &lt;em&gt;done&lt;/em&gt; in
a &lt;em&gt;real-world&lt;/em&gt; environment where &lt;em&gt;interactions&lt;/em&gt; with that
non-functional world is the primus motor. So why make &lt;em&gt;that&lt;/em&gt; painful?&lt;/p&gt;

&lt;p&gt;Erlang is a functional language which understands its purpose of
interacting with the non-functional real world. Functional but does
not try to whack you with the &lt;em&gt;+4 Mace of Lambda the Pure&lt;/em&gt; every time
you interact with the world.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Interestingly I see a pattern in my choice of programming
languages. The languages I use the most have the following traits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Good package management with a centralized package directory.&lt;/li&gt;
  &lt;li&gt;Ability to write quick one-off programs easily (scripting).&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I could add “nice syntax” etc., but that’s beside the point. I don’t
do non-nice languages. I want to retain my sanity. (So goodbye the
lucrative MUMPS jobs there.)&lt;/p&gt;

&lt;p&gt;In a world where you &lt;strong&gt;do not&lt;/strong&gt; write your own JSON parser, networking
library, UI framework, HTTP request processor etc. etc. the ability to
&lt;strong&gt;easily&lt;/strong&gt; discover, pull and manage external dependencies is
important. My life is too short to waste on libraries and languages
which start with “to install, first … then … then” instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip
install thispackage&lt;/code&gt; or even “download, unpack, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./configure &amp;amp;&amp;amp; make
install&lt;/code&gt;”.&lt;/p&gt;

&lt;p&gt;Somehow Erlang falls short of my definition of “good package
management” and “good scripting”. Not by much, but still.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Retiring instance types?</title>
   <link href="http://santtu.iki.fi/2014/01/13/aws-retiring-instance-types"/>
   <updated>2014-01-13T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/01/13/aws-retiring-instance-types</id>
   <content type="html">&lt;p&gt;&lt;em&gt;TL;DR: AWS is building an interstellar spaceship.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt; is the canonical infrastructure cloud provider. EC2 beta was announced in 2006 and started with &lt;a href=&quot;http://bit.ly/19oRu5s&quot;&gt;just one instance type&lt;/a&gt;: m1.small.&lt;/p&gt;

&lt;p&gt;This day there are … a lot more instance types. From the simplified
&lt;a href=&quot;http://ec2pricing.iconara.info/&quot;&gt;EC2 instance type &amp;amp; pricing page&lt;/a&gt; I
can now count &lt;strong&gt;27 different instance types&lt;/strong&gt;: c1.medium, c1.xlarge,
c3.2xlarge, c3.4xlarge, c3.8xlarge, c3.large, c3.xlarge, cc2.8xlarge,
cg1.4xlarge, cr1.8xlarge, g2.2xlarge, hi1.4xlarge, hs1.8xlarge,
i2.2xlarge, i2.4xlarge, i2.8xlarge, i2.xlarge, m1.large, m1.medium,
m1.small, m1.xlarge, m2.2xlarge, m2.4xlarge, m2.xlarge, m3.2xlarge,
m3.xlarge and t1.micro. Just try to say those aloud in one go!&lt;/p&gt;

&lt;p&gt;This profileration is due to (I believe) three drivers: customer
demand, enterprise adoption and advances in hardware. &lt;strong&gt;This is
great&lt;/strong&gt;, I have no gripes about the usefulness of the new instance
types. I’ve had customer cases where “hi1.4xlarge” would have been the
perfect solution but just was not yet available. Similarly the
introduction of PIOPS and SSDs was a godsend for database-type
workloads.&lt;/p&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/Takiyasha_the_Witch_and_the_Skeleton_Spectre.jpg&quot; alt=&quot;Takiyasha the Witch and the Skeleton Spectre by Utagawa Kuniyoshi&quot; /&gt;&lt;/p&gt;
  &lt;figcaption&gt;
    &lt;p&gt;&lt;em&gt;Death of Instances&lt;/em&gt; by … errr, actually it’s
&lt;em&gt;Takiyasha the Witch and the Skeleton Spectre&lt;/em&gt; by Utagawa
Kuniyoshi (Image source: &lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Takiyasha_the_Witch_and_the_Skeleton_Spectre.jpg&quot;&gt;Wikimedia
commons&lt;/a&gt;)&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;hardware-generations&quot;&gt;Hardware generations&lt;/h2&gt;

&lt;p&gt;But what happens to old stuff? What about the old hardware? What about
m1.small which has been around for 7+ years?&lt;/p&gt;

&lt;p&gt;Currently the AWS instance types can be grouped to roughly three categories:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Shared core instance types&lt;/strong&gt; (t1.micro and m1.small). Here vCPUs
are not dedicated to an instance, but shared between multiple
instances (50% for m1.small, no information on t1.micro but I’d
expect its CPU allocation to be be both smaller and dynamic).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Generic instances&lt;/strong&gt; which have 1 vCPU = 1 dedicated core, but
otherwise don’t have any particular hardware affiliation — they are
primarily defined by (vCPUs, memory, disk capacity) tuple. This
includes all m1 and c1 class instance types (AWS specifies m1, m2
and c1 class instances to have “Intel Xeon Family” processor and
t1’s as “Variable”.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Hardware specified instances&lt;/strong&gt;, e.g. instance types which are
&lt;strong&gt;defined&lt;/strong&gt; by particular hardware. This includes g2.2xlarge (&lt;em&gt;“G2
instances provide access to NVIDIA GRID GPUs (“Kepler” GK104)”&lt;/em&gt;, from
&lt;a href=&quot;http://aws.amazon.com/ec2/instance-types/&quot;&gt;AWS&lt;/a&gt;) and c3 class
(&lt;em&gt;“Each virtual CPU (vCPU) on C3 instances is a hardware hyper-thread
from a 2.8 GHz Intel Xeon E5-2680v2 (Ivy Bridge) processor”&lt;/em&gt;)
among others. These also have 1 vCPU = 1 dedicated core.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;gpu-generation-gaps&quot;&gt;GPU generation gaps&lt;/h3&gt;

&lt;p&gt;It is easy to see that the last category will pose difficulties in the
future. The GK104 GPU is already a previous generation GPU with its
successor (GK110) having been in production since May 2013 (both are
based on the same GPU family architecture, e.g. Kepler). What happens
when GK104 becomes unavailable?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;AWS is not going to throw the g2.2xlarge machines to junk heap —
after all, they’re going to be deprecated over 5 years. So when GK104
GPUs become unavailable, AWS is likely to keep g2.2xlarge around but
crucially &lt;strong&gt;it is no longer able to increase g2.2xlarge capacity
even if demand increases&lt;/strong&gt; using GK104 alone.&lt;/p&gt;

    &lt;p&gt;(With one caveat, see end of this section.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GK110-based machines can then be introduced as g2.4xlarge or
other. Eventually, the successor to GK110 comes around and AWS faces
the same situation as above.&lt;/p&gt;

    &lt;p&gt;(It makes no sense for AWS to roll GK110 GPUs into g2.2xlarge as
even the lowest-specced GK110 die has 800 CUDA cores more. Why would
they give those away at the same price?)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This leads to interesting economical dynamics. Let’s assume that
year-to-year AWS purchases enough g2 class hardware to increase each
instance type’s capacity by 100% and each hardware generation is on
sale for 2 years, and that each new hardware generation will be
initially purchased at same capacity as the previous
generation. Looking at the graph below you’ll see that at year 3 the
first-generation g2.2xlarge will represent &lt;strong&gt;one fifth&lt;/strong&gt; of the total
available capacity. (&lt;strong&gt;Caveat emptor:&lt;/strong&gt; These values are completely
arbitrary, so don’t rely on them even if they would seem sensible.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/gpu-hardware-generations-capacity.png&quot; alt=&quot;Hypotethical g2 class instance capacity growth from hardware generation to next&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note that I’m counting instances, not CUDA cores in the above
graph!&lt;/strong&gt; Also, the choice of 4xlarge and 8xlarge is arbitrary, they
could be 3xlarge and 4xlarge equally well. My point is in hardware
generations, not per-instance computing horsepower.&lt;/p&gt;

&lt;p&gt;Assuming that in year 3 you are need some GPU horsepower, but you
would be satisfied with g2.2xlarge. There are two potential outcomes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;There is spare capacity and you’ll get the g2.2xlarge on-demand
instance.&lt;/p&gt;

    &lt;p&gt;Why would there be excess capacity available, assuming that the
demand has grown from year to year? A possible scenario is that
most of the demand has been satisfied with newer g2.4xlarge and
g2.8xlarge instance types leaving the g2.2xlarge capacity
underused.&lt;/p&gt;

    &lt;p&gt;That, of course, is a problem for AWS since they have hardware but
no-one is paying for its use. (Opportunistic use of GPUs via spot
market can provide some help, but in this case spot prices are
going to be substantially less than on-demand prices thus not
offsetting the loss of demand completely.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Demand for GPU instances is much more evenly distributed, most
likely due to people trying to pick up most cost-effective instance
types. This means that demand for g2.2xlarge is substantial, yet
since its total capacity (in this model) is just 1/5 of the total
g2 class capacity your request is often blocked since &lt;strong&gt;no
capacity&lt;/strong&gt; is available.&lt;/p&gt;

    &lt;p&gt;This is problematic for you, of course, but it might be a publicity
problem for AWS, too (“AWS unable to meet up to customer demand!”
would the &lt;strike&gt;tabloids&lt;/strike&gt; blogosphere scream.)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AWS is going to handle this situation somehow. It is possible to
control demand via pricing. Future GPUs may support GPU virtualization
(Kepler already has some hardware virtualization support) in a way
that allows more flexible partitioning of GPU resources between
multiple instances. They might do something else. I don’t know.&lt;/p&gt;

&lt;p&gt;Anyway. If the first case happens and g2.2xlarge instances go fallow
and there’s no demand for them after 1-2 years then how long is AWS
going to keep them taking space in racks and costing maintenance
effort? In this case there is bound to be a write-off at some point
and the whole instance type would be nixed from inventory.&lt;/p&gt;

&lt;p&gt;However even if they manage to keep g2.2xlarge instance demand up &lt;strong&gt;at
some point hardware maintenance is going to exceed the marginal
profit&lt;/strong&gt; gained from keeping g2.2xlarge instances running instead of
using the same space, electricity and personnel for something
other. Since it is not possible to replace failed machines with
identically speced machines (remember, GK104 no longer in production
at that point), hardware failures are also going to slowly drain the
instance type capacity down too.&lt;/p&gt;

&lt;p&gt;So my final point is this: &lt;strong&gt;for instance types specified in terms of
hardware, it is likely that they have a limited lifetime&lt;/strong&gt; as that
particular instance type (the hardware may live on, repurposed to
serve another instance class).&lt;/p&gt;

&lt;p&gt;When the underlying hardware becomes unavailable and that instance
type’s capacity cannot be increased anymore, its fate is set. The
maximum lifetime is the useful lifetime of the hardware (about 5
years), but due to economic reasons it may be also less.&lt;/p&gt;

&lt;h3 id=&quot;cpu-generations&quot;&gt;CPU generations&lt;/h3&gt;

&lt;p&gt;Note that the above reasoning applies also to c3 and other classes
that are specified by their CPU type. Yet, for CPUs the situation
might be a little different. The t1, m1, m2 and c1 classes already run
on multiple CPU generations. As Ou et al. show in their paper
&lt;a href=&quot;https://www.usenix.org/system/files/conference/hotcloud12/hotcloud12-final40.pdf&quot;&gt;&lt;em&gt;Exploiting hardware heterogeneity within the same instance type of
amazon
EC2&lt;/em&gt;&lt;/a&gt;
there are several CPU generations with &lt;strong&gt;different performance&lt;/strong&gt;
already deployed in AWS.&lt;/p&gt;

&lt;p&gt;So for those instance classes which are not bound to a specific set of
CPU or disk configuration AWS can just keep adding capacity using the
current hardware generation. Yes, some customers get more recent
(e.g. more powerful) hardware, but if you are really interested in raw
performance these aren’t really your choice anyway.&lt;/p&gt;

&lt;p&gt;Eventually c3 class with Intel Xeon E5-2680 will suffer the same fate
as g2.2xlarge with Kepler GK104 — that specific CPU won’t be available
indefinitely. Will AWS at this point introduce c4, and let c3 keep
running as long as it is economically sensible?&lt;/p&gt;

&lt;p&gt;Alternatively AWS may choose to re-define c3 to have a physical
processor as &lt;em&gt;“Intel Xeon E5-2680 or &amp;lt;whatever is the next
generation&amp;gt;”&lt;/em&gt; and keep it running with the same caveats about
hardware heterogeneity as t1/m1/m2/c1 classes.&lt;/p&gt;

&lt;p&gt;One more possibility is that if AWS introduced c4, what would they do
with c3 capacity &lt;em&gt;in case its demand goes down&lt;/em&gt;? Since the hardware is
completely capable of being serving the non-hardware specific instance
types (t1/m1/m2/c1) &lt;em&gt;it is possible&lt;/em&gt; that AWS decides to move any
machines no longer in demand into “graveyard” instance types where the
specific CPU classification is not relevant.&lt;/p&gt;

&lt;h2 id=&quot;what-lies-in-the-future&quot;&gt;What lies in the future?&lt;/h2&gt;

&lt;p&gt;I have no idea how AWS plans to handle changes in hardware in the long
run. Maybe they’ll keep adding new instance classes and types. Maybe
they’ll re-define instance class specifications. Maybe something else
happens.&lt;/p&gt;

&lt;p&gt;While writing this post I came up with the following insights:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;m1/m2/c1 generation-to-generation performance gap keeps
growing. Eventually that gap between the first and latest generation
may become too large so that it will affect their users
detrimentally (“What? 2x difference between execution times on same
instance type?”) if left unchecked.&lt;/p&gt;

    &lt;p&gt;The 1 vCPU = 1/2 core (m1.small) and 1 vCPU = 1 core guarantee
(others) prevents more fine-grained core sharing in these (unless
re-defined). It might be possible that AWS will move older
generation machines into serving t1 class instances. They might even
introduce t1.small, t1.medium or other t1 classes to supplement the
t1.micro instance type (these wouldn’t get any vCPU-to-core matching
guarantee, meaning less predictable performance profile) as well as
to act as “graveyard” for servers from retired classes or from
classes with substantially decreased demand.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;c1 class feels the odd ball out. c3.large is better than c1.medium
(being only $0.005 more expensive) and c3.2xlarge beats c1.xlarge
($0.040 increase). I don’t really see any reason to use c1 instances
over c3 instances.&lt;/p&gt;

    &lt;p&gt;(Apart from the anecdotal information about low c3 instance
availability, which I believe will eventually be sorted out.)&lt;/p&gt;

    &lt;p&gt;BTW, the same applies between m2.xlarge ↔ m3.xlarge, m2.2xlarge ↔
i2.xlarge and m2.4xlarge ↔ i2.2xlarge instance types. m2 instances
have slightly, but not substantially more memory whereas m3 and i2
instances have either more or same number of vCPUs and way faster
SSD disks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I don’t believe low-end instances will be retired any time. AWS
needs a broad range of instance types to cover different needs and
the t1.micro and m1.small especially fill a need of
as-cheap-as-possible instance types for situations with low
performance requirements. It might become impossible to keep
performance divide between m1.small hardware generations, in which
case AWS might redefine m1.small’s performance characteristic
upwards and move oldest hardware generations to serving t1 class
instances (it is no coincidence that &lt;a href=&quot;http://amzn.to/19oVyCF&quot;&gt;t1.micro’s maximum CPU
performance is 2× m1.small’s&lt;/a&gt;).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want my guess on which instance types will be retired first, my
guess is &lt;strong&gt;something from c1 or m2 classes&lt;/strong&gt;. At least unless their
prices get substantially cut to make them cost-competetive with m3 and
i2 classes to keep demand (and cash flow) up.&lt;/p&gt;

&lt;h3 id=&quot;how-does-this-affect-you&quot;&gt;How does this affect you?&lt;/h3&gt;

&lt;p&gt;First of all,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;There is no way that the profileration of instance types won’t be
followed by some sort of change. Whether it is a cull of instance
types, redefinition of their specifications or something completely
different, I don’t know. But I know that there is no sensible future
where AWS can have gazillion instance types and still keep
profitable and themselves and customers sane.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Don’t specify instance types in code.&lt;/strong&gt; The instance type used for
a particular purpose is &lt;strong&gt;configuration data&lt;/strong&gt; (in launch
configuration, in configuration file etc.). If c1.medium is going
away then you’ll just need to grep config data and not the code
(which may construct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;c1.medium&quot;&lt;/code&gt; as `“c1” + “.” +
    &lt;newline&gt;&quot;medium&quot;` which you won't find with simple grep at all).

&lt;/newline&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Have a policy where production instances must be attributable.&lt;/strong&gt;
If after all configuration references have been changed but you are
still seeing c1.medium instances it is super-useful that you can
determine what they are for and find the group / person
responsible. For this you can use tags like the built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Name&lt;/code&gt; or
introduce your own like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Product&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Responsible&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are concerned about instance availability,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Do not rely on availability of an instance type.&lt;/strong&gt; So you need
more capacity but fail launching the super-price-optimal c3.2xlarge?
Fall back and try launching two c3.xlarge instead, or c3.4xlarge or
even c3.8xlarge. Or switch to g2.2xlarge or m2.2xlarge. The more
heterogenous AWS’s instance lineup becomes the less likely I think
there is going to be capacity in &lt;strong&gt;all&lt;/strong&gt; instance types available
all the time. (This applies only if you have your own instance
management system, since AFAIK this is not possible with AWS auto
scaling.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally. &lt;strong&gt;My head hurts.&lt;/strong&gt; Picking an “optimal” instance type is
becoming more and more difficult. Yes, it is now possible to pick
“more optimal” instance type than before, but finding that “more
optimal” is taking more and more time than when there was a smaller
number of instance types. (Will AWS abandon instance types at some
point completely, allowing you to tune all the CPU/memory/disk
parameters freely?)&lt;/p&gt;

&lt;p&gt;This is starting to feel like the cereal aisle at the grocery
store. Are you going to pick up the müsli with “berries and nuts” or
“berries and plenty nuts” or “fresh nuts and berries” or “nut and
berry extragavanza” or just “plain” or …&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Replay</title>
   <link href="http://santtu.iki.fi/2014/01/07/replay-book"/>
   <updated>2014-01-07T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2014/01/07/replay-book</id>
   <content type="html">&lt;div style=&quot;margin: 0 10px; width: 30%; float: right;&quot;&gt;
  &lt;p&gt;&lt;a href=&quot;http://www.librarything.com/work/10131364&quot;&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/replay-book-cover.jpg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Lately I’ve been reading a book called &lt;a href=&quot;http://www.librarything.com/work/10131364&quot;&gt;&lt;strong&gt;Replay - The history of
video games&lt;/strong&gt;&lt;/a&gt; by
&lt;a href=&quot;http://www.tristandonovan.com/&quot;&gt;&lt;strong&gt;Tristan Donovan&lt;/strong&gt;&lt;/a&gt;. As the title
suggests, this is a book about the history of video and computer games
up to the year it was written, 2010. But it is much, much more than
just a record of games of the past!&lt;/p&gt;

&lt;p&gt;I’ve read quite a bit about computer, computing and gaming history and
I have to say this is &lt;strong&gt;one of the best books&lt;/strong&gt; in that lot. If not
&lt;strong&gt;the best&lt;/strong&gt; so far. This is not only because it is well written, nor
only because it feels like a proper global history of video games
(e.g. not being US-myopic), nor only because it digs and describes
trends and social causes for changes in games and markets. It is all
that, but most importantly &lt;strong&gt;it captures the excitement&lt;/strong&gt; of the
generations of young and focused game developers over the three
decades of time covered.&lt;/p&gt;

&lt;p&gt;I am not a game developer and probably at my age never will be. Yet I
feel connected — as much as the book is a trip down the memory lane (I
probably have played 50-70% of the 80’s games listed), it also brings
up strong memories of my personal history of late 90’s when I was part
of the “new media” internet startup bubble. It brings up memories of
the excitement of venturing on completely new and unresearched areas
of computing, business and entertainment. About how you can be
passionate about what you are doing. And sometimes, what kind of
&lt;small&gt;small&lt;/small&gt; effect your work can have.&lt;/p&gt;

&lt;p&gt;Whether you or someone else will agree with my view on the book is
likely to depend on how your own history connects with the themes of
the book. For myself the book gave me a whang that I still feel
resonating in me! When thinking about all of the pioneers and
breakthroughs in games covered in the book I cannot help but feel the
same optimistic giddiness right now too. It feels … good.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Freezing Travis</title>
   <link href="http://santtu.iki.fi/2013/12/18/freezing-travis"/>
   <updated>2013-12-18T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/12/18/freezing-travis</id>
   <content type="html">&lt;p&gt;This is just a quickie. While working on
&lt;a href=&quot;https://github.com/santtu/freezr&quot;&gt;freezr&lt;/a&gt; I decided to take a look at
&lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis CI&lt;/a&gt;, which is a &lt;em&gt;“hosted continuous
integration service for the open source community”&lt;/em&gt; (as they say).&lt;/p&gt;

&lt;p&gt;And wow, is it easy. It is.&lt;/p&gt;

&lt;p&gt;In just a few lines of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; and some clickety-clackety of
enabling github hooks to travis made all of new code to be
automatically tested in travis. Being free of charge for open source
projects just makes it doubly good!&lt;/p&gt;

&lt;p&gt;(Which reminds me, I’ll have to attach the OSI-approved license to
freezr. It is open source, but I haven’t just gotten around to writing the boring licensing stuff…)&lt;/p&gt;

&lt;p&gt;There was … well. Why am I always getting a &lt;strong&gt;gotcha&lt;/strong&gt; moment? Am I
just somehow abnormally suspectible to finding corner cases?&lt;/p&gt;

&lt;p&gt;Anyway, here’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;python&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;python&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;2.7&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;global&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;PATH=$PATH:$TRAVIS_BUILD_DIR/node_modules/.bin&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;npm install less coffee-script&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pip install .&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rabbitmq&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;make actual-test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The gotcha is getting node’s local install bin directory into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;
environmental variable. Travis by default &lt;strong&gt;does have&lt;/strong&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./node_modules/.bin&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; so &lt;strong&gt;unless&lt;/strong&gt; you change the current
working directory you have no problems in running npm-installed
programs.&lt;/p&gt;

&lt;p&gt;(Of course &lt;em&gt;I did change the working directory&lt;/em&gt; during tests.)&lt;/p&gt;

&lt;p&gt;So if you do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; in Travis, keep in mind that &lt;strong&gt;by default
the non-global NPM install bin directory is not necessarily found via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;&lt;/strong&gt;. That it works by default is a happy coincidence, not a
guarantee.&lt;/p&gt;

&lt;p&gt;(I could do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo npm install -g&lt;/code&gt;, but I try to avoid changing global
system state unless absolutely necessary.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ember - (A)bort, (R)etry, (F)ail? R</title>
   <link href="http://santtu.iki.fi/2013/12/11/retry-on-ember"/>
   <updated>2013-12-11T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/12/11/retry-on-ember</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;/2013/12/04/rest-mess&quot;&gt;Earlier&lt;/a&gt; I wrote about problems
I had while trying to develop an &lt;a href=&quot;http://emberjs.com&quot;&gt;Ember.js&lt;/a&gt;
application with a &lt;a href=&quot;http://django-rest-framework.org/&quot;&gt;Django REST
framework&lt;/a&gt;-based backend. I did
some research (I’ll get back to other results from that later) and
tried using &lt;a href=&quot;http://angularjs.org/&quot;&gt;AngularJS&lt;/a&gt; for browser-side
development, but it didn’t work out too well. I checked some other
client-side frameworks but I really, really wanted to have a good
model representation in the browser side code including relations
between models and I couldn’t find one that felt right.&lt;/p&gt;

&lt;p&gt;Eventually I decided to give it another go with Ember. I had an
earlier semi-static UI mock that I extended using Ember and static
fixtures. Which despite the steep learning curve eventually worked&lt;/p&gt;
&lt;strike&gt;great&lt;/strike&gt;
&lt;p&gt;well enough.&lt;/p&gt;

&lt;p&gt;Though I could not postpone the dealing with the backend indefinitely.&lt;/p&gt;

&lt;p&gt;I decided to ditch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ember-data-django-rest-adapter&lt;/code&gt; completely, the
main reason that I didn’t understand how I should format the backend
response just by looking at the code (and no docs on that,
unfortunately). It might be just the greatest thing since pre-buttered
bread slices, but I just couldn’t understand how to get it working
with the backend framework I was using &lt;em&gt;even&lt;/em&gt; when it is by name
supposed to work with it. Doh.&lt;/p&gt;

&lt;p&gt;This is an after-the-fact reconstruction from memory on how I
progressed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Attach a custom adapter based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.JSONAdapter&lt;/code&gt; (e.g. set
application’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ApplicationAdapter&lt;/code&gt; value ).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Try to understand what an adapter does and what a serializer does.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create a custom serializer. Wonder why some of the methods don’t
get called. Realize that should have used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REST*&lt;/code&gt; base classes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Change adapter and serializer to back from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.RESTAdapter&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.RESTSerializer&lt;/code&gt; correspondigly.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Hack hack hack …&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Eventually I got an adapter and a serializer with only a small number
of minor changes compared to the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.REST*&lt;/code&gt; versions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Custom &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extractSingle&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extractArray&lt;/code&gt; methods (which are called
indirectly by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.RESTAdapter.extract&lt;/code&gt;) that don’t look for subkeys,
but use the payload value directly (as a direct value map, or an
array of value maps, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[...]&lt;/code&gt; vs. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&quot;objects&quot;:[...]}&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyForAttribute&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyForRelationship&lt;/code&gt; which turn Ember Data
convention camelcase field names into underscored JSON data keys
(from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instanceId&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;instance_id&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pathForType&lt;/code&gt; that doesn’t do pluralization of resource name
(e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project&lt;/code&gt; resource list is at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/project&lt;/code&gt; and individual
resource at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/project/1&lt;/code&gt;).&lt;/p&gt;

    &lt;p&gt;(I still have to find a way to include the trailing slash in
requests, Ember Data seems to be stripping them away, what causes
extra redirects with Django REST framework. Or just specify
&lt;a href=&quot;http://django-rest-framework.org/api-guide/routers#simplerouter&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trailing_slash=False&lt;/code&gt;&lt;/a&gt;
for the API router.)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s it. Total size is about 20 LOC. I’m pretty surprised about
that the minimal changes needed over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.REST*&lt;/code&gt; classes. What I &lt;strong&gt;have
not&lt;/strong&gt; done is saving models to the backend — the code might be missing
functionality to make that possible.&lt;/p&gt;

&lt;p&gt;You can check the code out yourself at
&lt;a href=&quot;https://github.com/santtu/freezr&quot;&gt;github&lt;/a&gt;. At the moment the
client-side UI code is in
&lt;a href=&quot;https://github.com/santtu/freezr/tree/master/freezr/ui/static/freezr_ui/coffeescript&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freezr/ui/static/freezr_ui/coffeescript&lt;/code&gt;&lt;/a&gt;
directory.&lt;/p&gt;

&lt;p&gt;P.S. I had one major gotcha while doing this. I’ve documented that one
in an another &lt;a href=&quot;/2013/12/11/gotcha-beware-of-bidir-traffic&quot;&gt;blog post&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Gotcha!</title>
   <link href="http://santtu.iki.fi/2013/12/11/gotcha-beware-of-bidir-traffic"/>
   <updated>2013-12-11T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/12/11/gotcha-beware-of-bidir-traffic</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;(Note: The code examples below use
  &lt;a href=&quot;http://coffeescript.org/&quot;&gt;coffeescript&lt;/a&gt; instead of plain
  javascript. If you don’t know coffeescript here’s a quick cheat
  sheet: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@foo&lt;/code&gt; ≅ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.foo&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;() -&amp;gt; stmt&lt;/code&gt; ≅ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function () { stmt
  }&lt;/code&gt;. Additionally text in curly braces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{{…}}&lt;/code&gt; is Ember’s
  &lt;a href=&quot;http://emberjs.com/guides/templates/handlebars-basics/&quot;&gt;templating
  language&lt;/a&gt;.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;figure&gt;
  &lt;p&gt;&lt;img style=&quot;width: 45%;&quot; alt=&quot;Finnish road sign #122&quot; src=&quot;http://upload.wikimedia.org/wikipedia/commons/a/a4/Finland_road_sign_122.svg&quot; /&gt;&lt;/p&gt;
  &lt;figcaption&gt;
    &lt;p&gt;Finnish road sign number 122, “Two-way traffic”. (Source:
&lt;a href=&quot;http://commons.wikimedia.org/wiki/File:Kaksisuuntainen_liikenne_122.svg&quot;&gt;Wikimedia
Commons&lt;/a&gt;)&lt;/p&gt;
  &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;While &lt;a href=&quot;/2013/12/11/retry-on-ember&quot;&gt;doing a retry on Ember&lt;/a&gt; for freezr user interface, I hit a
problem I’d like to share with you. I didn’t find help on the internet
on this so I hope if someone hits the same problem this post will
help.&lt;/p&gt;

&lt;p&gt;Anyway, I hit one major gotcha that had me scratching my head for a
long time. I had used
&lt;a href=&quot;https://github.com/jgwhite/ember-time&quot;&gt;ember-time&lt;/a&gt; as a basis on how
to implement a “since state change” time display. Converting the
original code to coffeescript was straightforward (but see
&lt;a href=&quot;#update&quot;&gt;below&lt;/a&gt; for an update):&lt;/p&gt;

&lt;div class=&quot;language-coffee highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FromNowView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;extend&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nextTick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;null&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tagName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'time'&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Handlebars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'{{view.output}}'&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;moment&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fromNow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nextTick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;later&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;notifyPropertyChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;willDestroyElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancel&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nextTick&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;didInsertElement&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and it was used like this:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{{view &quot;App.FromNowView&quot; valueBinding=&quot;stateUpdated&quot;}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which worked great when the page was first loaded but &lt;strong&gt;it failed to
update the time view after updates&lt;/strong&gt;. I was really really
confused. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;state&lt;/code&gt; value was itself updated in the rendered view
correctly immediately after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.reload()&lt;/code&gt; finished, but text
derived from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stateUpdated&lt;/code&gt; field was not. &lt;strong&gt;WTF??&lt;/strong&gt; This is what was
happening in the browser:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/ember-binding-problem-problem-visual.png&quot; alt=&quot;How it looked&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Top row is what happened in the UI and the bottom ones showing what
the server actually sent to the client on state change from running to
freezing to frozen states. Why is it stuck on “for 4 hours”?&lt;/p&gt;

&lt;p&gt;Time to debug. So,&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;I checked the JSON response. Yep, it had the correct, updated value.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I wondered whether the name was somehow conflicting (it was
originally &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stateChanged&lt;/code&gt;), so I renamed the JSON field and model
field. No effect.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I put tons of log output statements in Ember end Ember Data
code. This was a great learning experience in itself, as now I have
a lot better understanding how Ember propagates value changes. Nice
stuff, I think. However digging deeper and deeper I kept seeing that
the &lt;em&gt;updated&lt;/em&gt; value was being passed correctly along, yet still
refusing to show up in the actual web page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I wondered whether the date attribute type was doing something fishy
and switched to string instead. No effect, the “bad” value
persisted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I searched the net high and low to no avail.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started to do voodoo coding. Poking at things and hoping the problem
is mysteriously fixed.&lt;/p&gt;

&lt;p&gt;Finally I added logging to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.attr&lt;/code&gt;’s use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ember.computed&lt;/code&gt; and …&lt;/p&gt;

&lt;div style=&quot;font-size: 300%; margin: 1em 0;&quot;&gt;
  &lt;p&gt;… all was made clear to me.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;All of the &lt;em&gt;other fields&lt;/em&gt; were getting the value
from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@_data&lt;/code&gt; element (which contained the updated values set by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DS.Model.setupData&lt;/code&gt;) &lt;em&gt;except&lt;/em&gt; — &lt;strong&gt;except&lt;/strong&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stateUpdated&lt;/code&gt; which
got its value from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@_attributes&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;At this moment I remembered what I earlier read about &lt;a href=&quot;http://emberjs.com/api/classes/Ember.Binding.html&quot;&gt;Ember
bindings&lt;/a&gt;. And that
there was a difference between &lt;em&gt;normal bindings&lt;/em&gt; and &lt;em&gt;one-way
bindings&lt;/em&gt;. And that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueBinding=&quot;stateUpdated&quot;&lt;/code&gt; did a binding on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.value&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt;. And that this was a
normal e.g. &lt;em&gt;two-way binding&lt;/em&gt; meaning that updates on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt; are propagated to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.value&lt;/code&gt; &lt;strong&gt;and
vice versa&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I was not getting the updated value from JSON response because &lt;strong&gt;I had
already overwritten it myself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the offending line:&lt;/p&gt;

&lt;div class=&quot;language-coffee highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;notifyPropertyChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'value'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This doesn’t actually change the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, but Ember doesn’t
know that so it propagates the event to the bound field of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt;, which eventually results in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.set('stateUpdated', «value»)&lt;/code&gt; where the new value was
actually the old value. I’ll try to put this into a picture.&lt;/p&gt;

&lt;p&gt;In the figure below I’ve used &lt;span style=&quot;color: white; background: green;&quot;&gt;green&lt;/span&gt; for events initiated by Ember Data and &lt;span style=&quot;color: white; background: red;&quot;&gt;red&lt;/span&gt; for those initiated
by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView&lt;/code&gt; and the gray arrows show bindings between
different Ember-controlled values. I refer to objects by their class
names, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt; below is &lt;em&gt;not&lt;/em&gt; a class field but a
field in an instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/ember-binding-problem-explanation-1.svg&quot; alt=&quot;How it worked incorrectly&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In the template the statement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueBinding=&quot;stateUpdated&quot;&lt;/code&gt; creates
the two-way fat gray arrow binding (top row). The binding from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.value&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.output&lt;/code&gt; is a one-way
binding and comes from the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;property('value')&lt;/code&gt; on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output&lt;/code&gt;
function (right column). Finally the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.output&lt;/code&gt; binding
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{{view.output}}&lt;/code&gt; comes from somewhere deep
inside the templating system (bottom row).&lt;/p&gt;

&lt;p&gt;The initial value is loaded by Ember Data and is propagated from top
left corner by the green arrows. First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt; is
changed, which then propagates to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.value&lt;/code&gt;, which in
turn causes the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.output&lt;/code&gt; to change, which
finally causes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{{view.output}}&lt;/code&gt; template to
be (re-)rendered. This will in turn cause the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; chain to propagate
back in the chain, finally resulting in the nicely formatted time
delta value to be written into the HTML page for user to see.&lt;/p&gt;

&lt;p&gt;This is where the call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; messes things up. It will be called
every second, and it will call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notifyPropertyChange('value')&lt;/code&gt; which
in turn causes &lt;strong&gt;two&lt;/strong&gt; propagations to occur — one back to the
&lt;strong&gt;original&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Project.stateUpdated&lt;/code&gt; value thus &lt;strong&gt;overwriting it&lt;/strong&gt;, and
the other to propagate to the output template. This meant that the
output value was correctly updated as time passed, but any change in
the actual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stateUpdated&lt;/code&gt; value as reported by the backend was &lt;strong&gt;not&lt;/strong&gt;
reflected in the human-readable output.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(I’m not sure, but I think Ember’s idea is that since I’ve
overwritten the values myself it will keep them around until I call
either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rollback&lt;/code&gt;. I’m not sure whether it is sensible to
call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reload&lt;/code&gt; at all when you have uncommited changes in the
model.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Now that I had understood the true problem the solution came
immediately. In the application I just wanted to ensure that updates
on the bound value are propagated to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;App.FromNowView.output&lt;/code&gt;, which
was already automatically updating when the bound value was
changed. It also has to be refreshed as time progresses (“a few
seconds” → “a minute”) which &lt;em&gt;does not&lt;/em&gt; need to refresh the bound
value, just the &lt;em&gt;output value&lt;/em&gt;. The correct update sequence where
&lt;em&gt;display updates&lt;/em&gt; do not affect the actual state update time value is
shown in the picture below:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://santtu.iki.fi/assets/posts/ember-binding-problem-explanation-2.svg&quot; alt=&quot;How it works correctly&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tick&lt;/code&gt; will only cause the &lt;strong&gt;rendered&lt;/strong&gt; value to be updated while
all changes in the original model are &lt;strong&gt;also&lt;/strong&gt; honored. The change is
trivially simple with changing the property change event fired on the
&lt;em&gt;output&lt;/em&gt; element:&lt;/p&gt;

&lt;div class=&quot;language-coffee highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nextTick&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Ember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;later&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;notifyPropertyChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'output'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tick&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this simple change everything was finally made good!&lt;/p&gt;

&lt;p&gt;So what’s the lesson learned? When using Ember, &lt;em&gt;you need to
understand how a value is bound, to where, and what type of binding
makes sense for any particular situation&lt;/em&gt;. Also don’t use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@notifyPropertyChange&lt;/code&gt; indiscriminantly on values that are bound
&lt;em&gt;from outside the caller’s control&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a name=&quot;update&quot;&gt;&lt;/a&gt;&lt;strong&gt;Update:&lt;/strong&gt; Ember-time itself has since been fixed.  You’ll need to
look at
&lt;a href=&quot;https://github.com/jgwhite/ember-time/tree/bf3383c691bd7f60aafb96ddd7926be3196f1dfd&quot;&gt;bf3383c6&lt;/a&gt;
or earlier commit to see the original version.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Idempotent PUT is a fake</title>
   <link href="http://santtu.iki.fi/2013/12/05/idempotent-put-is-a-fake"/>
   <updated>2013-12-05T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/12/05/idempotent-put-is-a-fake</id>
   <content type="html">&lt;p&gt;Previously I poured my thoughts on &lt;a href=&quot;/2013/12/04/rest-mess&quot;&gt;REST/JSON protocol differences&lt;/a&gt;. I am still researching
on how different server and client frameworks work, but as an
interlude I’ll comment on the interpretation of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; operation in
relation to its use on “RESTful” APIs.&lt;/p&gt;

&lt;p&gt;I’ve seen a lot of people state that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT /resource/&amp;lt;id&amp;gt;&lt;/code&gt; should
create the resource if it does not exist. Like
&lt;a href=&quot;http://www.slideshare.net/stormpath/rest-jsonapis/23&quot;&gt;here&lt;/a&gt;,
&lt;a href=&quot;http://stackoverflow.com/a/12957114/779129&quot;&gt;here&lt;/a&gt; and
&lt;a href=&quot;http://stackoverflow.com/a/630475/779129&quot;&gt;here&lt;/a&gt; and
&lt;a href=&quot;https://github.com/toastdriven/django-tastypie/blob/master/tastypie/resources.py#L1386&quot;&gt;here&lt;/a&gt;
and and.&lt;/p&gt;

&lt;p&gt;This is absolutely &lt;strong&gt;wrong&lt;/strong&gt;. This is a misinterpretation of
&lt;em&gt;idempotency&lt;/em&gt;. Following this logic to the extreme causes both
&lt;em&gt;semantic&lt;/em&gt; and &lt;em&gt;practical&lt;/em&gt; problems.&lt;/p&gt;

&lt;h3 id=&quot;idempotency&quot;&gt;&lt;a name=&quot;idempotency&quot;&gt;&lt;/a&gt;Idempotency&lt;/h3&gt;

&lt;p&gt;I am making a strong statement here regarding PUT semantics here, so
let me first introduce you to the idea of idempotency. I’ll quote from
the &lt;a href=&quot;http://en.wikipedia.org/wiki/Idempotence&quot;&gt;wikipedia entry on
idempotence&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Idempotence (/ˌaɪdɨmˈpoʊtəns/ eye-dəm-poh-təns) is the property of
  certain operations in mathematics and computer science, that can be
  applied multiple times without changing the result beyond the
  initial application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And here is a small light switch system which has both idempotent and
non-idempotent functions:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;on-or-off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; sets lights on or off&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights-toggle!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you repeatedly call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights&lt;/code&gt;, you’ll get the same value every
time. The getter is both safe (no side effects) and idempotent
(returns same value on repeated calls). Similarly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt;
safe (it has a world-changing side effect) but is idempotent:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights-toggle!&lt;/code&gt;, of course, is not idempotent.)&lt;/p&gt;

&lt;p&gt;Now you are asking me what’s in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; function I didn’t show
you earlier. I’ll show you now:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;on-or-off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;boolean?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;boolean?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;on-or-off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;on-or-off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is an idempotent function. As long as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights-state&lt;/code&gt; stays
boolean (guaranteed if only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toggle-lights!&lt;/code&gt; are used to
change light state) it will change the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights-state&lt;/code&gt; to
match the request.&lt;/p&gt;

&lt;p&gt;Now the surprising bit. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights-state&lt;/code&gt; is not a boolean value,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights-state&lt;/code&gt; is &lt;em&gt;still&lt;/em&gt; an idempotent function and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; are too!&lt;/p&gt;

&lt;p&gt;Now consider a multi-user system (aka real world) where this happens:&lt;/p&gt;

&lt;div class=&quot;language-scheme highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;Me&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;Elsie&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set!&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lights-state&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'explode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;Me&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lights!&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;#t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; just making sure&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;'explode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Boom! What happened? Wasn’t &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; supposed to be idempotent? Yes,
and it still is. But wait, &lt;strong&gt;I thought that idempotency means that any
idempotent operation should work the same if repeated later!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;blink&amp;gt;&amp;lt;huge&amp;gt;Nope.&amp;lt;/huge&amp;gt;&amp;lt;/blink&amp;gt;&lt;/p&gt;

&lt;p&gt;Let’s go back to wikipedia entry and scroll a bit down:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A composition of idempotent methods or subroutines, however, is not
  necessarily idempotent if a later method in the sequence changes a
  value that an earlier method depends on – idempotence is not closed
  under composition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;“Not closed under composition”&lt;/em&gt;. Technically, when you call a
function (method, procedure, script, whatever) in a real-world
situation its result is a composition of the current system state,
inputs you provided and the function implementation
itself. Idempotency guarantees that any changes to the system state by
the idempotent operation are such that calling the same operation with
the &lt;em&gt;updated system state&lt;/em&gt; will result in the same final result as
calling with the &lt;em&gt;unaltered&lt;/em&gt; system state.&lt;/p&gt;

&lt;p&gt;What it does &lt;strong&gt;not guarantee&lt;/strong&gt; is that if you call with &lt;strong&gt;some other&lt;/strong&gt;
system state you would get the same results. If &lt;strong&gt;anyone else&lt;/strong&gt; has
changed the system state between &lt;strong&gt;your&lt;/strong&gt; calls to the idempotent
routine, then the system state &lt;strong&gt;has changed&lt;/strong&gt; and there are &lt;strong&gt;no
guarantees&lt;/strong&gt; that the result from your call will be the same. This is
exactly what happened, Elsie changed the system state, so even though
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lights!&lt;/code&gt; functions are still idempotent, &lt;em&gt;my&lt;/em&gt;
operations from &lt;em&gt;my&lt;/em&gt; viewpoint are &lt;em&gt;not&lt;/em&gt; since the two calls were
composed differently.&lt;/p&gt;

&lt;p&gt;At this point you should realize that when standards talk about
&lt;a href=&quot;https://svn.tools.ietf.org/svn/wg/httpbis/draft-ietf-httpbis/25/p2-semantics.html#idempotent.methods&quot;&gt;idempotency&lt;/a&gt;
or behavior of repeated
&lt;a href=&quot;https://svn.tools.ietf.org/svn/wg/httpbis/draft-ietf-httpbis/25/p2-semantics.html#PUT&quot;&gt;PUTs&lt;/a&gt;
they are &lt;em&gt;not&lt;/em&gt; guaranteeing you that all your PUTs will give the same
response or have the same effect in the system every time under all
conditions. What the operation idempotency guarantee can give you is
that when the composition of your PUT has &lt;em&gt;not changed&lt;/em&gt; (apart from
the changes the &lt;em&gt;original&lt;/em&gt; PUT made), subsequent PUTs should give you
the same result. But only when that assumption holds, otherwise we
&lt;em&gt;are not talking about idempotency at all&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;put-doesnt-have-to-create-resources&quot;&gt;PUT doesn’t have to create resources&lt;/h3&gt;

&lt;p&gt;The normal life cycle of any object, entity or resource within
computer systems is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It does not exist.&lt;/li&gt;
  &lt;li&gt;It is created.&lt;/li&gt;
  &lt;li&gt;Stuff happens to it.&lt;/li&gt;
  &lt;li&gt;It is destroyed.&lt;/li&gt;
  &lt;li&gt;It is no more.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Interpretation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DELETE&lt;/code&gt; operations are straightforward
if you think of them as steps #2 and #4 respectively. They manage the
life cycle of the resource. The resource exists between creation and
destruction, and otherwise exists not.&lt;/p&gt;

&lt;p&gt;If we take the viewpoint that these are the &lt;strong&gt;only&lt;/strong&gt; operations to
manage a resource’s lifecycle — and I urge you to take this viewpoint
too — then &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; is valid only during step #3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; &lt;strong&gt;should not&lt;/strong&gt; create a resource.&lt;/p&gt;

&lt;p&gt;Now I can already hear an argument in the line of “but using PUT to
create new resources &lt;em&gt;is&lt;/em&gt; an idempotent operation” and you are
right. If you define PUT to create non-existent resource and update an
existing resource, then two sequential PUTs will always get the same
result (even if the resource didn’t exist in the first place). But
this is circular reasoning. You can’t argument that PUT should be a
&lt;strong&gt;life cycle operation&lt;/strong&gt; because it &lt;strong&gt;can be&lt;/strong&gt; one while staying
idempotent. We can define that PUT is &lt;strong&gt;not a life cycle operation&lt;/strong&gt;
and it still stays an idempotent operation (PUT on non-existent
resource would result in the same result both times – a failure).&lt;/p&gt;

&lt;p&gt;At this point it should be clear that saying that “PUT should create
resources because of idempotency” is a false argument because
idempotency holds even if this is not the case.&lt;/p&gt;

&lt;p&gt;Which way PUT swings is a design choice. A choice.&lt;/p&gt;

&lt;p&gt;I want to convince you that it should &lt;strong&gt;not&lt;/strong&gt; create resources.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Ed: Changed “strawman argument” to “false argument”
above. Thanks Frederic for pointing out the semantic difference!)&lt;/small&gt;&lt;/p&gt;

&lt;h3 id=&quot;puts-on-deleted-resources&quot;&gt;PUTs on DELETEd resources&lt;/h3&gt;

&lt;p&gt;Now I’ll try to convince you why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; as a life cycle operation is
not a good idea from developer’s perspective because it just causes
practical implementation problems (and if you are not aware of these,
it can create hidden semantic traps in your system).&lt;/p&gt;

&lt;p&gt;This is a real-world case (simplified though):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;User 1 creates a message (POST).&lt;/li&gt;
  &lt;li&gt;User 1 edits the message (GET, PUT).&lt;/li&gt;
  &lt;li&gt;User 2 sees the message and decides to open it for editing (GET).&lt;/li&gt;
  &lt;li&gt;User 1 decides the message is crap and removes it (GET, DELETE).&lt;/li&gt;
  &lt;li&gt;User 2 updates the message (PUT).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you allow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; to implicitly create non-existent resources, you
get what I’d call &lt;em&gt;semantically inconsistent result&lt;/em&gt;. For users, the
message exists when it should not. This is entirely consistent from
system’s point of view, since the message created at step #5 is not
the same message that was deleted at #3.&lt;/p&gt;

&lt;p&gt;Unfortunately most of the systems that are written are meant for
&lt;em&gt;human&lt;/em&gt; consumption and need to work with &lt;em&gt;human expectations&lt;/em&gt;. Thus
in this case the implicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; most definitely was &lt;em&gt;definitely not
helping&lt;/em&gt; system development at all.&lt;/p&gt;

&lt;p&gt;Oh no, wait! Here’s another!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;User 1 has CREATE permission on messages.&lt;/li&gt;
  &lt;li&gt;User 2 has EDIT permission on messages.&lt;/li&gt;
  &lt;li&gt;User 3 has REMOVE permission on messages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think you can already guess where this is going. If there’s implicit
create on PUT I have to check for CREATE permission in two different
places, both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt;. (This is another real-world scenario
where some people can CREATE and EDIT, others can only EDIT and some
DELETE &lt;strong&gt;but not&lt;/strong&gt; create or edit. Auditability requirements…)&lt;/p&gt;

&lt;h3 id=&quot;what-then-is-put&quot;&gt;What then is PUT?&lt;/h3&gt;

&lt;p&gt;Simple:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It is &lt;em&gt;idempotent&lt;/em&gt;. (See &lt;a href=&quot;#idempotency&quot;&gt;above&lt;/a&gt; on limits.)&lt;/li&gt;
  &lt;li&gt;It operates on &lt;em&gt;existing&lt;/em&gt; resources.&lt;/li&gt;
  &lt;li&gt;It is &lt;strong&gt;not a life cycle operation&lt;/strong&gt;. It cannot create or destroy
resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Idempotent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; still stays the very same and very powerful and
useful feature as before as it allows you to just repeat the request
in case of transient network or server failures. Just please don’t
think &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PUT&lt;/code&gt; as a life cycle management operation, because it should
not be.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>REST MESS</title>
   <link href="http://santtu.iki.fi/2013/12/04/rest-mess"/>
   <updated>2013-12-04T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/12/04/rest-mess</id>
   <content type="html">&lt;p&gt;While working on a hobby project called
&lt;a href=&quot;https://github.com/santtu/freezr&quot;&gt;freezr&lt;/a&gt; I came across a few
assumptions I had made which turned out to be &lt;em&gt;wrong&lt;/em&gt;. I’m going to
write a bit about these assumptions, since I found solving the
resulting problems very frustrating.&lt;/p&gt;

&lt;p&gt;I had decided to write freezr API-first instead of UI-first. The
reason for this decision was based on that&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;I had a very good understanding of the problem and what kind of
actions it offered to the user, so there was no need to research the
problem through UI prototypes etc. (&lt;em&gt;If you do not have a good
understanding of the problem, you should &lt;strong&gt;always&lt;/strong&gt; start with UI
mockups and prototypes.&lt;/em&gt;)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I am very much in favor of delegating the web server to provide
interfaces to core logic and let the browser be the UI (e.g. HTML5
web application). This means that “web server’s” role is really to
provide an HTTP API to the core services, and the only bit of
user-visible “web serving” happens when it bootstraps the
browser-based application.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I am &lt;em&gt;not&lt;/em&gt; a UI designer nor UI developer. I’m much more a service
architect and developer. I can do UIs that are best described as
“engineering UIs”, functional, but not pretty and definitely not
having thought too much about usability. In particular, I was hoping
to get someone else to actually do the UI bit for me — another
reason for postponing UI development.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I worked on freezr for a few weeks, on and off, and got it to a
situation where the service itself was functional (albeit lacking a
lot of production-level stuff like authentication, access control
etc.) and passed quite a lot of unit and integration tests. The
integration tests drove the service via its defined REST API alone.&lt;/p&gt;

&lt;p&gt;I wrote the server using &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;Django&lt;/a&gt;. I
had a few reasons to pick up Django, one of them being familiarity
with it. That’s familiarity, &lt;em&gt;not liking&lt;/em&gt;. I don’t like Django that
much, I’ve struggled with it in the past, but I still find it a quick
way to get an web app from zero to development demo. Albeit, it is
always a bit of a frustrating experience. I could have used Flask, but
I’m not as familiar with it, and the times I’ve used it I’ve found
writing quite a bit of boilerplate code for things that come as
default in Django.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(As a side note: I don’t like node.js, so I’m not going to use
Meteor or its ilk. I find it frustrating to write in a language that
has practically zero thought given towards developer friendliness,
&lt;a href=&quot;https://www.destroyallsoftware.com/talks/wat&quot;&gt;orthogonality or understandable error and exception
handling&lt;/a&gt;. If I could
decide, I’d replace JavaScript with a standardised &lt;em&gt;and well designed&lt;/em&gt;
bytecode interpreter where browsers would provide a
JavaScript-to-bytecode compiler shim for backwards compability. It
could even use &lt;a href=&quot;http://llvm.org/&quot;&gt;LVVM&lt;/a&gt; representation directly. This
would give it much better re-targetability from other
languages.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Anyway, I ended up using Django with the &lt;a href=&quot;http://django-rest-framework.org/&quot;&gt;Django REST
framework&lt;/a&gt;. I have worked with
TastyPie and found it &lt;em&gt;superlatively frustrating experience&lt;/em&gt; when
trying to do anything “out of the tastypie box” so I was absolutely
sure that I would not touch it even with a long stick (unless it had a
very, very sharp end with a nuclear option installed). (TastyPie might
have gotten better since, so you shouldn’t take my opinion as anything
else than an opinion.)&lt;/p&gt;

&lt;p&gt;So I wrote a REST interface using REST framework. I think it ended up
nice and orthogonal. I especially liked the way how the framework made
it easy to provide URIs for resource references. Like this (edited for
brevity):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;small&gt;
GET /api/account/1/
HTTP 200 OK

{
    &quot;id&quot;: 1,
    &quot;domain&quot;: &quot;http://localhost:8000/api/domain/1/&quot;,
    &quot;name&quot;: &quot;AWS account&quot;,
    &quot;access_key&quot;: &quot;AKIAJH3LIPN74P3XO3UQ&quot;,
    &quot;active&quot;: true,
    &quot;projects&quot;: [
        &quot;http://localhost:8000/api/project/1/&quot;,
        &quot;http://localhost:8000/api/project/2/&quot;
    ],
    &quot;regions&quot;: [
        &quot;us-east-1&quot;
    ],
    &quot;instances&quot;: [
        &quot;http://localhost:8000/api/instance/13/&quot;,
        &quot;http://localhost:8000/api/instance/14/&quot;,
        &quot;http://localhost:8000/api/instance/15/&quot;,
        &quot;http://localhost:8000/api/instance/16/&quot;,
        &quot;http://localhost:8000/api/instance/17/&quot;,
        &quot;http://localhost:8000/api/instance/18/&quot;
    ],
    &quot;updated&quot;: &quot;2013-11-29T13:19:17.963Z&quot;,
    &quot;log_entries&quot;: [
        {
            &quot;type&quot;: &quot;info&quot;,
            &quot;time&quot;: &quot;2013-11-28T20:58:19.900Z&quot;,
            &quot;message&quot;: &quot;Regions changed&quot;,
            &quot;details&quot;: &quot;Added: us-east-1\nRemoved: none&quot;
        },
        {
            &quot;type&quot;: &quot;info&quot;,
            &quot;time&quot;: &quot;2013-11-28T20:58:38.929Z&quot;,
            &quot;message&quot;: &quot;Refreshed 1 regions in 1.15 seconds, total 6 / added 6 / deleted 0 instances&quot;,
            &quot;details&quot;: null
        },
	...
    ],
    &quot;url&quot;: &quot;http://localhost:8000/api/account/1/&quot;
}
&lt;/small&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using URIs for resource references makes the whole API &lt;em&gt;theoretically&lt;/em&gt;
to have a very nice property: as long as the “root” point is known, it
is possible to find all resources in the system without any need of
the resource URL syntax. The interface itself will tell you that
instance 15 is located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:8000/api/instance/15/&lt;/code&gt;
without you having to know &lt;em&gt;anything&lt;/em&gt; about the URL structure. For all
you care, you could have instance 15 in a completely different URL
from other instances like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://fnord:6643/ISTORE.JCL/?iid=i-6a56cd3&lt;/code&gt;. You, as a web browser
application programmer would &lt;em&gt;not&lt;/em&gt; have to do anything to support
distributed resources!&lt;/p&gt;

&lt;p&gt;I just &lt;em&gt;love&lt;/em&gt; the idea. I though the REST API was just what REST is
really meant to be — simple, using HTTP primitives, clean URLs, with
the whole data model traversable without having to know about the
particular service’s URL structure (the web server would tell the root
URL during bootstrapping).&lt;/p&gt;

&lt;p&gt;Hooray. Time to go do some UI development.&lt;/p&gt;

&lt;p&gt;For the UI side I decided to try out
&lt;a href=&quot;http://emberjs.com/&quot;&gt;Ember.js&lt;/a&gt;. I knew its data layer wasn’t yet
final, but I thought, what the heck, I’m doing pretty simple REST API
here, that shouldn’t be a problem.&lt;/p&gt;

&lt;p&gt;It was.&lt;/p&gt;

&lt;p&gt;This is &lt;em&gt;not&lt;/em&gt; Ember’s fault in itself. It is just that Ember’s REST
interface is designed to work with a &lt;em&gt;particular&lt;/em&gt; flavor of REST
interfaces. The REST API that &lt;em&gt;I&lt;/em&gt; had defined &lt;em&gt;did not&lt;/em&gt;
conform to this model. I searched the net for a solution, and found
&lt;a href=&quot;https://github.com/toranb/ember-data-django-rest-adapter&quot;&gt;ember-data-django-rest-adapter&lt;/a&gt;
which … didn’t work out too well either. It is not final either so I
should not expect too much, but it had the same problem as with
Ember’s default REST adapter: it was making a lot of assumptions about
the REST protocol. In particular, it didn’t work with resource
URIs. Well, no problem, I can just
&lt;tt&gt;&lt;strike&gt;Hyperlinked&lt;/strike&gt;ModelSerializer&lt;/tt&gt; to get IDs
instead. And it wanted to pluralize resources in URIs, e.g. &lt;em&gt;a&lt;/em&gt;
project was fetched from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/api/project/ID/&lt;/code&gt; but list of projects from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/api/projects&lt;/code&gt;. Oh god. Then I found it actually was expecting
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hasMany&lt;/code&gt; relations as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[{&quot;id&quot;:1},{&quot;id&quot;:2}]&lt;/code&gt; and not just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,2]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;No, I’m not going down that rabbit hole.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If there is competition for most stupid convention ever, I’d
nominate the idea that &lt;em&gt;computers&lt;/em&gt; are required to &lt;em&gt;pluralize human
words&lt;/em&gt; when using a &lt;em&gt;computer-oriented API&lt;/em&gt; to distinguish between
fetching &lt;em&gt;a&lt;/em&gt; resource versus &lt;em&gt;many&lt;/em&gt; resources. Quick, what’s the
plural of &lt;strong&gt;“locus”&lt;/strong&gt;? What if your API describes shoe pairs
(e.g. shoes), is the resource point for fetching records of many shoes
then “shoess”?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Frustration and amazement.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I came to realize that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Most of the backend to browser development is done in a tightly
linked manner. They are collectively developed and either both of
those work well together (you picked rails-friendly framework for
rails backend), or either the browser side gives in (custom resource
adapter) or the server side caves in (doing whatever is required for
the responses to conform to client expectations).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There is no universal “way of doing REST”. &lt;em&gt;I though&lt;/em&gt; I understood
this, but I had just thought the disperancies were in resource
access and action definitions, not so much in how the resources are
serialized and deserialized to/from JSON format.&lt;/p&gt;

    &lt;p&gt;&lt;small&gt;(Example of different action definitions: In freezr, a
project is frozen with a POST to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/api/project/1/freeze/&lt;/code&gt;. Another
and entirely valid choice would have been to apply PATCH to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/api/project/1/&lt;/code&gt; with content of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ 'state': 'freezing' }&lt;/code&gt;, where
instead of defining an action, the request would declare the desired
state.)&lt;/small&gt;&lt;/p&gt;

    &lt;p&gt;In reality there are many ways to do these, and &lt;em&gt;most frameworks are
designed to work only with one particular REST protocol&lt;/em&gt; without
thought given to reconfigurability for different use cases. (The
configuration of REST adapters mostly concerns with endpoint URL and
what combinations of operations is used for different idioms like is
partial change PUT or PATCH, can you POST over an existing record?)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I don’t know jack shit.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix the last problem I’m going to do some research on different
REST interface patterns and which server- and client-side frameworks
use then, and write a follow-up blog post on what I find out.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Working on freezr</title>
   <link href="http://santtu.iki.fi/2013/11/29/working-on-freezr"/>
   <updated>2013-11-29T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/11/29/working-on-freezr</id>
   <content type="html">&lt;p&gt;Just a quick post — I’m working now on something I call &lt;em&gt;freezr&lt;/em&gt;. It
is is a) a hobby project and b) based on a real world need. Since it’s
a hobby project it is also naturally an open source project (or at
least will be when I get around tacking license information into the
repository) and located, of course at
&lt;a href=&quot;https://github.com/santtu/freezr&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>My old flame ... from 17 years past</title>
   <link href="http://santtu.iki.fi/2013/11/03/my-old-flame"/>
   <updated>2013-11-03T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/11/03/my-old-flame</id>
   <content type="html">&lt;p&gt;Before I get about talking old stuff, here’s a few &lt;strong&gt;important&lt;/strong&gt;
suggestions for anyone who came here looking for my old MD5 Java
implementation (in case you don’t know, MD5 is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Cryptographic_hash_function&quot;&gt;cryptographic hash
function&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Firstly, &lt;strong&gt;do not use it.&lt;/strong&gt; There are plenty of good alternatives starting
  from Java’s standard library’s
  &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/security/MessageDigest.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.security.MessageDigest&lt;/code&gt;&lt;/a&gt;
  up to separate open-source implementations such as
  &lt;a href=&quot;http://www.bouncycastle.org/docs/docs1.5on/org/bouncycastle/crypto/digests/MD5Digest.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org.bouncycastle.crypto.digests.MD5Digest&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Secondly, &lt;strong&gt;do not use MD5 at all.&lt;/strong&gt; MD5 has not been considered
secure enough for new applications for over a decade now. Use SHA256
or better instead. It’s of course another issue if you’re working
with legacy protocols, but for any &lt;strong&gt;new&lt;/strong&gt; implementation you just
&lt;strong&gt;do not use MD5&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Thirdly, if you are planning to do what seems to be every new web
site programmers thing, that is, when you’ve come to realize that
storing plaintext passwords is &lt;strong&gt;bad&lt;/strong&gt; and have come up with the
idea of storing passwords as hashes, and were thinking of using MD5
for that — and of course now you’d be thinking of SHA256 instead —
&lt;strong&gt;do not use a cryptographic hash function for password
hashing&lt;/strong&gt;. Use a hash function &lt;em&gt;specifically designed for long-term
secure password hash storage&lt;/em&gt; such as
&lt;a href=&quot;http://en.wikipedia.org/wiki/PBKDF2&quot;&gt;PBKDF2&lt;/a&gt;. Just don’t use a
plain hash function for password hashing. Trust me.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;And of course if all of the above is new news for you, &lt;strong&gt;please
please please&lt;/strong&gt; get some education. I &lt;strong&gt;pathologically hate closet
cryptographers&lt;/strong&gt; e.g. people who think they know everything about
cryptography since they’ve finally succeeded in breaking out of a
wet paper bag.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason for this post is that I still keep getting e-mails for
support and questions about an MD5 Java implementation I wrote a
&lt;em&gt;looooooong&lt;/em&gt; time ago (1996). It is so long time ago that in a few
years people starting their professional programming careers will be
&lt;em&gt;younger&lt;/em&gt; than that piece of code.&lt;/p&gt;

&lt;p&gt;(Oh boy, am I old.)&lt;/p&gt;

&lt;p&gt;So if you have come here to report a bug in my MD5 implementation or
have a question about how to use it, now you have the full story why
it is effectively abandonware (which it sort of isn’t, since it is
under LGPL and has thus been incorporated to many other codebases) —
and that it is usable in &lt;em&gt;and relevant&lt;/em&gt; to only a very narrow set of
programming problems, which &lt;em&gt;yours most likely is not one of them&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I don’t even have the source online anymore. I find keeping it online
pointless for the reasons listed above. If you are super-interested in
the source, just search for &lt;a href=&quot;https://www.google.com/search?q=md5+paavolainen&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;md5
paavolainen&lt;/code&gt;&lt;/a&gt;,
although a lot of the hits are actually derived (mostly better!)
implementations.&lt;/p&gt;

&lt;p&gt;Why did I write an MD5 Java implementation in the first place?&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Imagine the following spoken with a hoarse, oldtimer voice,
worn rough by the dust inhaled by years in solitude service among
racks and racks of ancient servers.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Well, this happened in 1996 when Java was still at version 1.0.2 and
did not have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java.security&lt;/code&gt; package at all (it came along in 1997). I
just needed MD5 in a browser Java applet for the purpose of signing a
request sent to backend server (implemented in C as a module to CERN
httpd, oh the times) on a research project into micropayments. I
didn’t find a ready-to-use MD5 Java class (the Internet was much
smaller back then) so I wrote one following almost 1:1 the RSA
C-language reference implementation. (The micropayment project never
got anywhere practical, but that’s a whole another story…)&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(Back to normal voice.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;P.S. I’m not saying that I’m offended by people e-mailing me about the
MD5 class — on the contrary, it does feel good to know you have made -
albeit very small - but a lasting contribution to the “great internet
of buzzwords”. What I sincerely hope for is that those e-mail would
stop, not because I don’t like them, but because MD5 in general, and
definitely not my unmaintained implementation of it &lt;em&gt;should not be
used anymore&lt;/em&gt;. Move along, don’t dwell in the cryptographic past.&lt;/p&gt;

&lt;p&gt;P.P.S. I’ll be more positive on the next post, I promise.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Life's easier if you can code</title>
   <link href="http://santtu.iki.fi/2013/10/28/life-is-easier"/>
   <updated>2013-10-28T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/10/28/life-is-easier</id>
   <content type="html">&lt;p&gt;If you have never ever programmed anything, you can find the title of
this post strange. Are programmers somehow superhuman, capable of
lifting railroad cars with their bare hands? Are they more
intelligent, more capable than other people? Or is there a secret
cabal of programmers where by joining you’ll get secret discounts at
electronics stores and easier promotions at work?&lt;/p&gt;

&lt;p&gt;Oh I just wish even just the second to last would be true, but alas,
none of the above.&lt;/p&gt;

&lt;p&gt;Being a programmer does not make you fitter (strangely often the
opposite), nor stronger. But it does help quite a lot in many
things. It’s also possible to do some &lt;a href=&quot;http://www.youtube.com/watch?v=ukpBk3vvue8&quot;&gt;really cool
things&lt;/a&gt; if you mix in with
some physical world stuff with the programming. However that’s not the
kind of “making life easier” stuff I’m really talking about.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I was inspired to write this post because I’m trying to sell some
stuff, mostly old magazines boxed up (why I have kept them in the
first place, though?). There’s a nice free-to-advertise
craigslist-style site used here in Finland that I’ve used before
&lt;em&gt;but&lt;/em&gt;. The &lt;em&gt;but&lt;/em&gt; is there’s a length limit on the ad and I’ve got
&lt;em&gt;tons&lt;/em&gt; of those magazines to sell. Itemizing them goes over the length
limit many times over.&lt;/p&gt;

&lt;p&gt;So what do I do?&lt;/p&gt;

&lt;p&gt;I whip up a &lt;a href=&quot;http://www.python.org/&quot;&gt;Python&lt;/a&gt; script using
&lt;a href=&quot;http://genshi.edgewall.org/&quot;&gt;Genshi&lt;/a&gt; formatting an
&lt;a href=&quot;http://yaml.org/&quot;&gt;YAML&lt;/a&gt; input file. The output is a bunch of text
files, broken down by magazine names. Here it is, a total 9 lines of
code:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env python3
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;genshi.template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yaml&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;yaml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data.yaml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;tmpl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genshi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NewTextTemplate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;template.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mags&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magazines&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'out/'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;, &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'.txt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Time spent:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Script: 10 minutes&lt;/li&gt;
  &lt;li&gt;Writing text template: 5 minutes&lt;/li&gt;
  &lt;li&gt;Reformatting data to YAML: 30 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not bad — I did have the magazine data already available (text file,
needing some reformatting for YAML) so this went quite nicely. After
this effort I basically need just to log into the classified site and
copy-paste the data file by file. (If I had really literally tons of
ads to place I’d scripted the uploading part too, but I have just
tens. Not worth optimizing that.)&lt;/p&gt;

&lt;p&gt;Eventually I had to reformat the output several times before the site
grokked it. I would hate even the &lt;em&gt;potential&lt;/em&gt; of having to re-do
something that tedious by hand, so I’m positive about the result.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There is great benefit in optimizing repeated tasks (xkcd has a nice
&lt;a href=&quot;http://xkcd.com/1205/&quot;&gt;illustration&lt;/a&gt; about it). Here I needed the
script only once, so I’m not sure whether I came out ahead time-wise,
but definitely I didn’t get to experience the tedium of doing so.&lt;/p&gt;

&lt;p&gt;Come to think about it, the reason I did use templating was probably
to &lt;em&gt;avoid a tedious task&lt;/em&gt; by turning it into a &lt;em&gt;programming
problem&lt;/em&gt;. Writing a small script to do the task at least gave me a
feeling of &lt;em&gt;being productive&lt;/em&gt; even if it might not have been so.&lt;/p&gt;

&lt;p&gt;Ha! Maybe that’s it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Being able to write programs makes life easier by allowing you to
turn (some) tedious tasks into interesting programming problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m happy with that.&lt;/p&gt;

&lt;p&gt;P.S. So what about Excel? I do actually find spreadsheets quite useful
as an miniature programming platforms when the data I’m manipulating
is already in tabular form. Doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=if($B4&amp;lt;&amp;gt;&quot;&quot;;TRUE;FALSE)&lt;/code&gt; and
copy-pasting it over a row is often faster than writing and debugging
an imperative program.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>One viewpoint on cloud computing</title>
   <link href="http://santtu.iki.fi/2013/07/10/one-viewpoint-on-cloud"/>
   <updated>2013-07-10T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/07/10/one-viewpoint-on-cloud</id>
   <content type="html">&lt;p&gt;Recently I was consulting a client on cloud strategy. When we were
trying to explain to the client how the risk landscape with growing
adoption of cloud computing (being the case that it affects them even
if they don’t themselves use cloud services) … I had an idea.&lt;/p&gt;

&lt;p&gt;An idea that I think gives some insight why enterprises and especially
IT companies were slow on cloud uptake and why small and agile
startups were quick to take up on it.&lt;/p&gt;

&lt;p&gt;Before I get to the actual idea, I need to go through some background
information first. If you’re super duper familiar with risk management
in IT service procurement, feel free to skip ahead.&lt;/p&gt;

&lt;h2 id=&quot;bloody-long-introduction&quot;&gt;Bloody long introduction&lt;/h2&gt;

&lt;p&gt;So, you know what risk is?
&lt;a href=&quot;https://en.wikipedia.org/wiki/Risk#Quantitative_analysis&quot;&gt;Wikipedia&lt;/a&gt;
puts it this eloquently:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;risk = probability × loss
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is if you have a 0.5% yearly probability event that costs you
$1M, and another with 50% probability and a loss of $10,000 these are
crudely equal with expected yearly losses of $5,000 for &lt;strong&gt;both&lt;/strong&gt;. So
you’ll take both the probability of a bad thing happening and the
consequences of that thing happening &lt;strong&gt;together&lt;/strong&gt; as a risk.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Caveat emptor: This is only one viewpoint on risk.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This view of risks comes with an attached, implicit viewpoint. It is
viewed as &lt;strong&gt;my&lt;/strong&gt; risk. For example, the risk to me of &lt;strong&gt;your&lt;/strong&gt; house
catching fire is neglible (being non-neglible only if you happen to
live within 100 meters), because the &lt;strong&gt;loss to me&lt;/strong&gt; of your house
burning is zero → my risk is zero too.&lt;/p&gt;

&lt;p&gt;In larger businesses and government agencies it is common to push
enterprise’s risk (“my”) to the vendor (“your risk”) through
contractual means. In areas of IT service procurement this means the
service provider assumes liabilities on not meeting service level
agreements / deviating from rules and regulations / other failures. In
exchange to .. well, of course, higher fees.&lt;/p&gt;

&lt;p&gt;So, the risk &lt;strong&gt;probability&lt;/strong&gt; can be divided into two components:
&lt;strong&gt;mine&lt;/strong&gt; and &lt;strong&gt;yours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The service provider may mitigate its risks by many means. It might
employ quality process models and employ good quality hardware as well
as cover residual risks with insurances, for example. (More cynically
oriented might expect the vendor to not do so.)&lt;/p&gt;

&lt;p&gt;Anyway this does provide two more aspects to consider when
understanding the &lt;strong&gt;loss&lt;/strong&gt; component. For this discussion I’ll split
it into &lt;strong&gt;methods&lt;/strong&gt; and &lt;strong&gt;means&lt;/strong&gt;. Processes and hardware, if you
like.&lt;/p&gt;

&lt;p&gt;So we get to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;risk coverage = (me ⇆ you) × (methods ⇆ means)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ignore the pseudo-scientific notation for a minute. What I mean here is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(me ⇆ you)&lt;/code&gt;  &lt;/p&gt;

    &lt;p&gt;You can push risk probability to someone else, or handle it
yourself.  Not surprisingly corporate and governmental organizations
tend to push risks away from themselves. After all it is easier to
say &lt;em&gt;“We had a contract with ACME Corp. to cover all bases! They
fucked up!”&lt;/em&gt; than to &lt;em&gt;“It was our fault.”&lt;/em&gt;  &lt;/p&gt;

    &lt;p&gt;You can always count on people in large entities to &lt;em&gt;cover their
asses&lt;/em&gt; without regard to global optimum - it’s not their money,
after all.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Methods and means relate .. here’s an example.  &lt;/p&gt;

    &lt;p&gt;One network security risk aspect is the management of firewalls. To
have good security you need to have good processes to ensure that
only the minimum set of required holes are used, knowledge to
understand the security model, an audit trail of changes, and so on.&lt;/p&gt;

    &lt;p&gt;Good processes don’t mean anything without some means to turn those
processes into the desired action. In this example that would
require an actual network firewall (hardware). You can wish and
design and change manage all you want but without a firewall those
policies would have zero effect (e.g. you’d have no network
security, or alternatively no network, both of which would be bad
for business).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally we are getting close to the &lt;strong&gt;cloud&lt;/strong&gt;. So bear with me.&lt;/p&gt;

&lt;p&gt;The “traditional” way to manage IT service risks was to let the
service vendor handle the risk. The risk coverage model was a bit like
below (with dashes on non-relevant things):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my risk coverage =   (me ⇆ ---) × (------- ⇆ -----)
your risk coverage = (-- ⇆ you) × (methods ⇆ means)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;small&gt;(Note: I’m not sure whether the word “coverage” is a good
choice here. Can’t figure out anything better, though…)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;When shit then did hit the fan it was &lt;strong&gt;you&lt;/strong&gt; (the vendor) that had to
handle bad publicity and the resulting loss of income (sanctions,
paybacks etc.). There are some risks that cannot be transferred
(opportunity costs etc.), but generally my losses would be small-ish.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;(There is a bank in Finland which has an IT service vendor
handle its computing needs. All the standard high quality goodies: hot
standby fail-over data center with redundant connectivity between the
two. The link was so redundant and reliable that when one of the
redundant links actually did &lt;strong&gt;fail&lt;/strong&gt;, it reliably caused the other
link to &lt;strong&gt;fail&lt;/strong&gt; at the same time. This kind of mind-blowing
cluster-fuckup cost the service vendor, but cost the bank probably
quite a lot too. Small-ISH is relative.)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;With the introduction of &lt;strong&gt;cloud computing&lt;/strong&gt; and its commodity
computing model the the coverage handling of risks has changed:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my risk coverage   = (me ⇆ ---) × (methods ⇆ -----)
your risk coverage = (-- ⇆ you) × (------- ⇆ means)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now a cloud computing provider’s job is to provide the &lt;strong&gt;technical&lt;/strong&gt;
services I have purchased at an agreed SLA. However the cloud vendor
&lt;strong&gt;does not&lt;/strong&gt; take the responsibility to ensure that I would use its
services either correctly or effectively! In a cloud computing
environment &lt;strong&gt;I must now handle processes&lt;/strong&gt; that make effective use of
the means provided by the cloud vendor.&lt;/p&gt;

&lt;p&gt;Going back to the firewall example with &lt;a href=&quot;http://aws.amazon.com&quot;&gt;Amazon Web
Services&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;AWS is liable if it fails to either a) provide the firewall services
(security groups, VPC network ACLs) with agreed availability or b)
they have other functional problems (like passing traffic not
explciitly allowed).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;AWS &lt;strong&gt;is not&lt;/strong&gt; liable if &lt;strong&gt;I do “allow all from all”&lt;/strong&gt; and someone
hacks the system when I didn’t do the methods bit properly. I have
to understand and implement the methods to use the means AWS
provides to meet my own business goals.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;finally-a-point&quot;&gt;Finally, a point&lt;/h2&gt;

&lt;p&gt;Out of this comes the synthesis of the great idea I referred earlier:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The introduction of cloud computing doesn’t substantially change IT
service risks, but it does change the distribution of these risks
between the client and the service provider.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What’s so &lt;strong&gt;bloody difficult&lt;/strong&gt; in this for many enterprise and
governmental clients is that &lt;strong&gt;for years they have oursourced all IT
risk management processes and now they would have to learn to handle
it themselves&lt;/strong&gt; (or find someone else to do that — a market that
didn’t exist when cloud computing came around).&lt;/p&gt;

&lt;p&gt;Alternatively said:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Earlier, the negotiation of distribution of risk between clients and
  service providers was a business negotiation, an exchange of
  responsibilities and liabilities versus fees required to accept
  those responsibilities and liabilities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cloud computing in contrast is a &lt;strong&gt;commodity&lt;/strong&gt; market where the
  service provider tries to minimize negotiations with the clients by
  providing a limited set of contract options for its clients.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;so-wtbf-about-startups&quot;&gt;&lt;a name=&quot;startups&quot;&gt;&lt;/a&gt;So WTBF about startups?&lt;/h2&gt;

&lt;p&gt;Well think about it.&lt;/p&gt;

&lt;h3 id=&quot;10-years-ago&quot;&gt;10 years ago&lt;/h3&gt;

&lt;p&gt;You’re a startup. You need IT service. You go to a IT provider. You
are so bloody small, they give you a crap deal. You can’t negotiate —
it’s either their way, or the highway. You call some other vendors,
but in the end you’re really negotiating just different shades of
blue. So you sign.&lt;/p&gt;

&lt;p&gt;Then they blow up. You go out of business. (The contract? Yeah, good
luck in trying. Even if you win, their standard contract you had to
accept doesn’t give you back the business you lost. Remember, you’re a
startup, you don’t have the capital to survive someone else’s
fuck-up. Your house was next to my tinderbox.)&lt;/p&gt;

&lt;h3 id=&quot;when-cloud-computing-comes-around&quot;&gt;When cloud computing comes around&lt;/h3&gt;

&lt;p&gt;You’re a startup. You need IT service. You go to a cloud
provider. They give you just one deal, the same deal everybody
gets. You can’t negotiate — it’s either the cloud way, or get a TARDIS
and go back 10 years (previous chapter).&lt;/p&gt;

&lt;p&gt;(Then they blow up. Same situation as 10 years back, minus the
lawyer.)&lt;/p&gt;

&lt;p&gt;So …&lt;/p&gt;

&lt;p&gt;Startups have never ever had the chance to negotiate risks on the same
level as enterprises. Earlier they had to take the crap
deal. (Alternatively they had to live in the shadows of the “real” IT
economy, that is, hugging servers and trying to negotiate a reasonable
deal with ISPs to get fat enough Internet pipe and worry the hair gray
about their cheap hardware and colo deals.)&lt;/p&gt;

&lt;p&gt;When cloud computing came around it offered &lt;strong&gt;no worse&lt;/strong&gt; risk
distribution than startups ever had to handle, yet it offered &lt;strong&gt;new
capabilities&lt;/strong&gt; that the earlier model lacked.&lt;/p&gt;

&lt;p&gt;No wonder startups embraced the cloud. Even with an unknown future,
the cloud was guaranteed to be &lt;strong&gt;no worse&lt;/strong&gt; than what was available
before.&lt;/p&gt;

&lt;h2 id=&quot;afterword&quot;&gt;Afterword&lt;/h2&gt;

&lt;p&gt;This is just one viewpoint. Making an assumption that this would be
the &lt;strong&gt;only&lt;/strong&gt; reason for success and fast adoption of cloud computing
in startups is both wrong and retrofitting the facts to a fabricated
historical narrative. Don’t fall for that. Reality is much, much more
complex.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Enter Jekyll (where's Hyde?)</title>
   <link href="http://santtu.iki.fi/2013/07/08/jekyll-and-hyde"/>
   <updated>2013-07-08T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/07/08/jekyll-and-hyde</id>
   <content type="html">&lt;p&gt;Live and learn. &lt;a href=&quot;/2013/04/12/can-you-blog-in-github&quot;&gt;Earlier&lt;/a&gt;
I wondered whether I could use a github repository as a place to publish a blog. Essentially my original plan was to use the plain repository view as a way to render ReST formatted pages. But it got a bit unwieldy very fast after that.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A blog needs a feed. A blog without a feed isn’t a blog, at least by
my definition. So I thought about writing a short script to read the
page titles from RST files and output an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.atom&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rss&lt;/code&gt; formats
(and wrote one).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You still need a “master” page for random visitors so they can see
what you’ve written lately. Ok, not a biggie either.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;And … !!!!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No!&lt;/strong&gt; I’m not going that way, &lt;strong&gt;again&lt;/strong&gt;. I’ve written static website
and blog generators before and I know where this path would lead me
to. There has to be a better way! Surely my idea of using github as a
blogging platform, surely there must be programmers who also &lt;abbr title=&quot;Don't Repeat Yourself&quot;&gt;DRY&lt;/abbr&gt;.&lt;/p&gt;

&lt;p&gt;Of course I had seen and heard about
&lt;a href=&quot;http://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; but had somehow completely
bypassed them earlier. Funny how you can ignore so completely
something you sort of know. I guess if someone had come to me a month
back and asked “You know about github pages?” I’d certainly answered
“Yep, you can host static web sites and blogs there.” Somehow I just
didn’t make the connection between
&lt;a href=&quot;/2013/04/12/can-you-blog-in-github&quot;&gt;what I was looking for&lt;/a&gt; and
&lt;a href=&quot;http://pages.github.com/&quot;&gt;what’s available&lt;/a&gt;. C’est la vie.&lt;/p&gt;

&lt;p&gt;Alas, github pages isn’t a complete solution to your blogging
needs. It does come with &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; static site
generator which will help a lot in creating a website by either
automating a lot of the legwork or by providing ready-made
abstractions for wrapping custom stuff in Liquid templates.&lt;/p&gt;

&lt;p&gt;I took a look at some of the
&lt;a href=&quot;https://github.com/mojombo/jekyll/wiki/sites&quot;&gt;example Jekyll-generated sites&lt;/a&gt;. Some
are very pretty, and I’m impressed by the fact that sites like
&lt;a href=&quot;http://developmentseed.org/&quot;&gt;Development Seed&lt;/a&gt; can be generated via
Jekyll. (Or maybe I shouldn’t. HTML5 makes that very possible. Perhaps
it is more impressive that the site has been made despite problems
that Jekyll has probably created… there’s no perfect tool, and I
would assume Development Seed’s creators have hit a few gotchas along
the way.)&lt;/p&gt;

&lt;p&gt;“But still”, I was thinking, “do I have to write all those templates
just to get a working static blog generator?”&lt;/p&gt;

&lt;p&gt;So, if you’re thinking about creating your blog on GitHub pages using
Jekyll, here’s what I found out:
&lt;strong&gt;&lt;a href=&quot;http://jekyllbootstrap.com/&quot;&gt;Jekyll Bootstrap&lt;/a&gt;&lt;/strong&gt;. Quickly, do this!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ sudo gem install jekyll
$ git clone https://github.com/plusjade/jekyll-bootstrap.git USERNAME.github.io
$ cd USERNAME.github.io
$ rake post title=&quot;Hello World&quot;
$ jekyll server -w
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and then browse to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:4000&lt;/code&gt;. You’ll see an example post
and the one you just created before (&lt;em&gt;Hello World&lt;/em&gt;). You’ll find the
sample post in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; directory. Edit it. Reload the page in
browser. &lt;strong&gt;You can already see results!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step is to push your cloned repository to your own account
under github — you’ll need to 1)
&lt;a href=&quot;https://github.com/repositories/new&quot;&gt;create the repository&lt;/a&gt;, 2)
update repository url at your checked-out Jekyll bootstrap repository
and 3) push.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git remote set-url origin git@github.com:USERNAME/USERNAME.github.io.git
$ git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME&lt;/code&gt; really should be your &lt;strong&gt;own&lt;/strong&gt; github username
when you push. Earlier when cloning it was just a directory name, but
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set-url&lt;/code&gt; it &lt;strong&gt;must&lt;/strong&gt; match your github username. &lt;em&gt;You won’t see
your pages in github pages&lt;/em&gt; unless you push to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;your
username&amp;gt;.github.io&lt;/code&gt; repository.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;By the way — Jekyll bootstrap uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME.github.com&lt;/code&gt; in its
examples, yet GitHub Pages keeps talking about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME.github.io&lt;/code&gt;
(&lt;em&gt;com&lt;/em&gt; vs. &lt;em&gt;io&lt;/em&gt;). Apparently there was a
&lt;a href=&quot;https://github.com/blog/1452-new-github-pages-domain-github-io&quot;&gt;renaming operation&lt;/a&gt;
moving user and project pages from github.com to github.io in
April 2013.  I tested that both schemes (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME.github.io&lt;/code&gt;
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME.github.com&lt;/code&gt; repository names) work, but accesses to
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USERNAME.github.com&lt;/code&gt; URL will redirect you to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github.io&lt;/code&gt;
address.  Note that Jekyll bootstrap instructions are likely to be
updated at some point in time, so this note about the inconsistency
might be obsolete by the time you read this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After you’re done pushing, wait a while and navigate to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://USERNAME.github.io/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;P.S. You can take a look &lt;a href=&quot;https://github.com/santtu/santtu.github.io/&quot;&gt;at the
repository&lt;/a&gt; for this blog.&lt;/p&gt;

&lt;p&gt;P.P.S. If you want to keep your blog’s version history clean from
Jekyll Bootstrap’s commit history, do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd USERNAME.github.io; rm -rf
.git; git init; git add .&lt;/code&gt;, commit changes with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m
'Historyless clone from Jekyll Bootstrap.'&lt;/code&gt; update origin with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git
remote add origin git@github.com:USERNAME/USERNAME.github.io.git&lt;/code&gt; and
do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push -u origin master&lt;/code&gt;. Just &lt;em&gt;don’t&lt;/em&gt; do this if you ever wish
to merge updates from the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll-bootstrap&lt;/code&gt; repository.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Can you blog in github?</title>
   <link href="http://santtu.iki.fi/2013/04/12/can-you-blog-in-github"/>
   <updated>2013-04-12T00:00:00+00:00</updated>
   <id>http://santtu.iki.fi/2013/04/12/can-you-blog-in-github</id>
   <content type="html">&lt;p&gt;I’ve written quite a lot in my life. Some of it has ended up in blogs
(now since gone, although I have archive copies), alas most
not. Mostly what I write is targeted towards a small audience —
customers, co-workers, friends. For those venues a blog isn’t actually
the best way (customers like .doc files, for co-workers email or
intranet work just fine, and Facebook and Twitter are great for
friends). Yet, sometimes I have a mysterious urge to spill my guts to
the wider world.&lt;/p&gt;

&lt;p&gt;I added a blog to wordpress.com some time earlier, then pulled its
plug without actually writing anything meaningful in there. Somehow I
felt a whole blog site, where I’d worry over presentation (I’m a
stickler for good design) over the content was
somehow.. unsatisfactory. Yet I’d definitely not want to host anything
myself, either.&lt;/p&gt;

&lt;p&gt;While this was swirling around my head (in a background process), I
thought about github. It is public. It can natively render
restructuredtext files natively to HTML — perhaps not so pretty, but
what the hell. Thanks got git itself, all of the data would be
version-controlled and securely replicated. Would that work?&lt;/p&gt;

&lt;p&gt;So that’s what I’m now trying to check out. Could I use github itself
to host a blog, with minimal maintenance and effort?&lt;/p&gt;

&lt;p&gt;I do see already some problems. How would you do a nice RSS feed? How
would I do linking between posts easy? And of course, how would I
handle comments?&lt;/p&gt;

&lt;p&gt;I’m not sure. I’ll find out soon enough.&lt;/p&gt;
</content>
 </entry>
 

</feed>
