Pension fund in Sweden, an overview

In Sweden, like many other western countries, each working person has an individual pension fund. This is vastly different from some other countries like Vietnam, where the pension fund is shared, not only between every working person, but also between other purposes (maternity leaves, sick leaves…) . Like many other things in Sweden, the pension fund is transparent to you, and you can manage part of it, to some level. If you do things “correctly”, then it might make a sizable impact on your pension you you retire

A three parts pension scheme

Pension fund in Sweden consists of 3 parts. If you have been in Sweden for more than 1 year, you can always check to see how much money you have in your pension fund (your information is only “added” in your first November here)

[censor output image]

General pension (Swedish: Allmän pension)

Every working person in Sweden will receive this pension, as contributed by their employer. Every year, 18.5% of your pensionable income, up to a limit, is contributed to this part of your pension. The limit is set as 7.5 PBA – Price Base Amount. This is adjusted by Swedish government every year, and in 2019, 1 PBA = 64.400 SEK, meaning your upper limit this year is 483.000SEK. If you are making more than that in your pensionable income (good for you!), then your public pension contribution is still capped at 89.355 SEK.

The public pension actually has 2 parts of itself:

The income pension (Inkomstpension)

which is 16% of your pensionable income. You can see this, (i.e. how much money do you have), but you can’t manage it. The state will invest the money the way it sees fit, however you can guess that the money is invested in some low risk, low return bonds.

The premium pension (premiepension)

which is 2.5% of your pensionable income. You can actually manage this at

By default, your premium pension is put into AP7 Såfa, which is actually a very good fund. It has very low fee (only 0.06 – 0.1%/year), and good return rate. It is also an adaptive fund, which means it will invest more in bonds (which is “safer”, but returns less than stocks) as you age. When you are less than 55 years old, 100% is your money is put into shares, and that will reduce as you age, at 65 (your expected retirement age), it’s 67% stocks and 33% bonds, at 75, it’s 33% stocks and 67% bonds

Pensionsmyndigheten is great, because not only you can manage your fund here, but also it has a wide range of funds for you to choose, at a superbly discounted fee. The discount is small on index funds (which already have cheap management fees by themselves), usually at 0.16%/year compared to 0.2%/year originally, but it is very significant for actively managed funds.

Most of them are discounted for more than 1%. For example: Skandia Time Global has a management fee of 1.4% year, and on top of that, you have to pay transaction fee (Transaktionskostnad) of 0.25%, in total your fee is 1.65%/year. At Pensionsmyndigheten you only pay 0.39%. Which means you get 1.26% gain per year for free! As the biggest fund manager in Sweden, they have the leverage to negotiate with other fund managers to cut down the fees, and that is really good for you.

You can leave your money as-is, I think the default choice is very decent. But you are free to make your bet to potentially make more money.

The only bad thing about Pensionsmyndigheten is that you can’t put more money to their fund, even if you want to. That low fee is just so great.

Occupational pension (Tjänstepension)

Most, but not all, employers in Sweden give their employees the occupational pension. In case your employer doesn’t – like mine – then you will likely have to pay it yourself.

Most of the companies follow ITP scheme, which is in short:

  • ITP1, for people who were born in 1979 and after, which is
    • 4.5% of your salary, up to 7.5 PBA/year, so basically 40.250SEK/month in 2019.
    • 30% of your salary part that is higher than 7.5 PBA/year.
  • ITP 2, for people who were born in 1978 and before
    • 10% of your pensionable income, up to 7.5 PBA
    • 65% of your pensionable income, from 7.5 to 20 PBA
    • 32.5% of your pensionable income, from 20 to 30 PBA

The numbers are updated here

So if your salary is higher than 40.250SEK, your occupational insurance increases very fast.

If you get less than, or equal to, 40.250SEK/month, then your total pension contribution is 23% of your pensionable income.

If you are get, for example, 50.000SEK/month, then your total pension contribution is as follow:

9250 SEK from general pension

1811.25 + 2925 SEK from occupational pension

Total: 13986.25 SEK = 27.9725%

So if you are a high income person, this part can be very significant in your pension fund, and by default you don’t have a good choice as with premium pension, so you should pay close attention to it.

Just like premium pension, you can of course manage this pension, even to a bigger extend, as you can choose the provider yourself. In many cases, however, the choices of provider can be limited, depending on your employer contract. Notable providers in the market are:

  • Most banks, including big fours (SEB, Swedbank, Nordea & Handelsbanken) and smaller ones (Skandia, Länsförsäkringar)…
  • Avanza
  • Nordnet
  • SPP
  • Söderberg & Partners

As always, it’s best to talk with your company HR and/or your fund manager to see which options do you have. I’d always recommend to choose the one which lowest fees (less than 0.3%/year) and the biggest fund portfolio. Note that the provider might have a more limited fund portfolio for pension, so make sure to check that.

With occupational pension you have too choices, or actually three:

  • Funds (Fondförsäkring)
  • Traditional insurance (Traditionell försäkring)
  • A mix between those two.

When I started paying my occupational pension, I went with Traditional insurance because I am clueless about other options. In the end, I moved my pension into funds. Why? Lower cost with higher return.

Skandia Traditionell försäkring: 0.55% management fee, with an average 8.4% return/year in the last 4 years (2014-2018), down to 5% from May 1st 2019.

An US index fund: 0.2% management fee, with an average 18%/year in the last 5 years.

It’s not even close! Assuming I put 5000 SEK/month into my occupational pension (which is not the actually number), and the traditional insurance return is 5.3%/year, while the index fund return is 9.5%/year – both after fees, after 30 years:

  • Traditional Insurance gives me 4.419.370 SEK
  • Us index fund gives me 10.245.650 SEK

The choice was easy!

What if you don’t know what funds to invest? Nordnet for example, provides about 1400 funds in their portfolio. Which to choose? A general recommendation is to invest your money into an index fund – a type of fund that follow an index, like Standard & Poor 500, passively. The common characteristics of index funds are they are very low cost (commonly 0.2%/year fee), they yield market return, which is, in most of the cases, very good. The average return for S&P 500 index since its inception has been about 9.7%/year.

A well known advice is to have a three parts portfolio: an US index fund (follow S&P 500 index), a global market index fund, and a total market bond fund. It’s up to you, your age, your risk tolerance … to decide how many percent you want to invest in each. If you ask me, then I’d would say invest into an US index fund (most banks have this fund), and forget about it. If you are older, then you might want to put part of your money into bonds, and if you are younger, you might want to bet by putting more money into actively managed funds – which might have higher return than index funds, but with higher fee. In long term, index funds should still be a majority of your investment portfolio. Avoid funds with high fees. Avoid paying for people to adjust funds for you – the less they take, the more you make.

Private pension

This is your own pension contribution. However since 1/1/2016 this is no longer a “tax deductible” contribution, so there are very few people are still contributing to this part. I personally don’t, so I will skip writing about it.


A super short review of XBox One X

I have been a PS4-fan (if I can call myself so) since the day I bought the original PS4 to play Dragon Age: Inquisition. At that point, PS4 is the clearly better choice than XBox One: smaller without a separate power adapter, 50% more powerful (1.84TFLOPS vs 1.23 TFLOPS), simpler policies to share/resell game, etc etc.

I even liked XBox One X when it was announced, it checks almost all the boxes, except for, well, games and price, so I gave it a pass, especially when I got a PS4 Pro from a colleague at a very good price. This genre, PS4 has won for many reasons, one of that is it has a excellent line of exclusive.

Why not all three of them? Why choose side?

And I remain faithful until the day Elgiganten – a big electronic retailer in Sweden sells Xbox One X with Fallout 76 bundle at an unbeatable price (cheaper than Xbox One X selling alone, so the game actually reduces the price of the bundle!). I talked to myself – why not, if I don’t like it I can just return (it’s turned out that the game is digital, so I won’t be able to return. But I like it in the end so I decided to keep it. I find myself playing Apex Legends every night now, and I’m happy with it)

I won’t play Fallout 76, but this is cheaper than the Xbox One X alone, thanks to it.

The good

A marvel of engineering. It’s significantly more powerful than my PS4 Pro, yet it is just the same size and is even more quiet.

Incredible value if you think about Game Pass. Bunch of good games at a very low price, especially when you use the promotions that happen all the time. I spent about 30 SEK (less than 4 USD) for 3 months of that.

The controller battery lasts me weeks, and it takes only 1 minute or so to replace the battery.

A new generation of gamers!

Games that are optimized for X run exceptionally well. Forza Horizon 4, Red Dead Redemption 2, just to name a few.

Xbox and Xbox 360 games backward compatibility.

UHD Blu-ray player.

The bad

The UI is a mess. I complained about how HBO UI is a mess . But I think XBox One UI is on par in term of terrible.

The ugly

The Blu-ray player that refuses to play my UHD bluray, 9 out of 10 times.

I will have to re-buy many games to get the advantage of native 4K.


Protected: NDepend, a (rather short) review

This content is password protected. To view it please enter your password below:

Commerce Episerver Order Uncategorized

Control the thousand separator for Money in Episerver Commerce

If you are selling goods in multiple markets which same currency but with different languages, such as EuroZone, you might notice that while everything looks quite good, except that the thousand separator might be off from time to time: it is always the same and does not change to match with the language, so sometimes it’s correct, sometimes it’s not.

Let’s take a step back to see how to properly show the thousand delimiter 

In the United States, this character is a comma (,). In Germany, it is a period (.). Thus one thousand and twenty-five is displayed as 1,025 in the United States and 1.025 in Germany. In Sweden, the thousands separator is a space.

You might ask why the problem happens with Episerver Commerce. In Commerce, each currency has an attached NumberFormatInfo which let the framework knows how to format the currency. During startup, the system will loop through the available CultureInfo and assign its .NumberFormat to the currency.

The problem is there might be multiple CultureInfo that can handle same currency, for example, EUR which is used across Eurozone, can be handled by multiple (20? ) cultures. However, the first matching CultureInfo to handle the format of the currency will be used. In most of the cases, it will be br-FR (because the CultureInfo(s) are sorted by name, and this CultureInfo is the first in the list to handle EUR)

br-FR does not have a thousand separator, but a whitespace. That’s why even if your language is de-DE, the amount in EUR will not be properly formatted as 1.234,45 but 1 234,45

How to fix that problem?

Luckily, we can set the NumberFormatInfo attached for each currency. If you are only selling in Germany, you can make sure that EUR is always formatted in German style, by adding this to one of your initialization modules:

But if you have multiple languages for one currency, this will simply not work (because it’s static, so it will affect all customer). Your only option is to avoid using Money.ToString(), but to use Money.ToString(IFormatProvider), for example

Assuming CultureInfo.CurrentUiCulture is set to correct one.

This, however, does not resolve the problem with merchandisers using Commerce Manager. They might have to work with orders from multiple markets, and for example, if your site is selling good stuffs in Europe, there are chances that merchandisers see the prices without correct thousand separator. Most of places in Commerce Manager uses Money.ToString(), and there is a reason for that: it’s too risky to use Money.ToString(CultureInfo.CurrentUICulture), because if a merchandiser uses English, he or she is likely gonna see money formatted as “$” instead of “€”, and that is a much bigger problem of itself.

Moral of the story: localization is hard, and sometimes a compromise is needed.

Commerce Episerver Performance Uncategorized

Fixing ASP.NET Membership performance – part 1

Even though it is not the best identity management system in the .NET world, ASP.NET Membership provider is still fairly widely used, especially for systems that have been running for quite long time with a significant amount of users: migrating to a better system like AspNetIdentity does not comes cheap. However, built from early days of ASP.NET mean Membership provider has numerous significant limitations: beside the “architecture” problems, it also has limited performance. Depends on who you ask, the ultimate “maximum” number of customers that ASP.NET membership provider can handle ranges from 30.000 to 750.000. That does not sound great. Today if you start a new project, you should be probably better off with AspNetIdentity or some other solutions, but if your website is using ASP.NET membership provider and there is currently no plan to migrate, then read on.

The one I will be used for this blog post has around 950.000 registered users, and the site is doing great – but that was achieved by some very fine grained performance tuning, and a very high end Azure subscription.

A performance overview 

I have been using ASP.NET membership provider for years, but I have never looked into it from performance aspects. (Even though I have done some very nasty digging to their table structure). And now I have the chance, I realize how bad it is.

It’s a fairly common seen in the aspnet_* tables that the indexes have ApplicationId as the first column. It does not take a database master to know it is a very ineffective way to create an index – in most of the cases, you only have on ApplicationId in your website, making those indexes useless when you want to, for example, query by UserId. This is a rookie mistake – a newbie tends to make order of columns in the index as same as they appear in the table, thinking, that that SQL Server will just do magic to exchange the order for the best performance. It’s not how SQL Server – or in general – RDBMS systems work.

It is OK to be a newbie or to misunderstand some concepts. I had the very same misconception once, and learned my lessons. However, it should not be OK for a framework to make that mistake, and never correct it.

That is the beginning of much bigger problems. Because of the ineffective order of columns, the builtin indexes are as almost useless. That makes the queries, which should be very fast, become unnecessarily slow, wasting resources and increasing your site average response time. This is of course bad news. But good news is it’s in database level, so we can change it for the better. It if were in the application level then our chance of doing that is close to none.

Missing indexes

If you use Membership.GetUserNameByEmail on your website a lot, you might notice that it is … slow. It leads to this query:

Let’s just ignore the style for now (INNER JOIN would be a much more popular choice), and look into the what is actually done here. So it joins 3 tables by their keys. The join with aspnet_Applications would be fairly simple, because you usually have just one application. The join between aspnet_Users and aspnet_Membership is also simple, because both of them have index on UserId – clustered on aspnet_Users and non-clustered on aspnet_Membership

The last one is actually problematic. The clustered index on aspnet_Membership actually looks like this

Uh oh. Even if this contains LoweredEmail, it’s the worst possible kind of index. By using the least distinctive column in the first, it defeats the purpose of the index completely. Every request to get user name by email address will need to perform a full table scan (oops!)

This is a the last thing you want to see in a execution plan, especially with a fairly big table. 

It should have been just

which helps SQL Server to use the optimal execution plan

If you look into Azure SQL Database recommendation, it suggest you to create a non clustered index on LoweredEmail. That is not technically incorrect, and it still helps. However, keep in mind that each non clustered index will have to “duplicate” the clustered index, for the purpose of identify the rows, so keeping the useless clustered index actually increases wastes and slows down performance (even just a little, because you have to perform more reads to get the same data). However, if your database is currently performing badly, adding a non clustered index is a much quicker and safer option. The change to clustered index should be done with caution at low traffic time.

Tested the stored procedure on database above, without any additional index

With new non clustered index

With new clustered index:

Don’t we have a clear winner?


Why I left Metacritic, for good.

I’m a mediocre gamer, by any measures, but that does not defy the fact that I love playing games. Great games, only. With my very limited time and budget, I must to be very selective about the games I play. For a very long time, Metacritic is my to-go website to check if I should play a game – and I set my rules rather high: anything less than 80 is a big no-no. Less than 85 is a no, unless it’s a sequel of a game I loved so much (so I can see how the story turned out to be). More than 85 is “I’ll think about it” (when it comes with a very tempting discount, I might make up my mind). A game of at least 90 Metacritic score will be in my short list (but not necessary in my playing list). A game of at least 95 Metacritic means “must try” for me. I might not love it, but a game with such reviews must have something I like about.

However, overtime, I did realize what MetaCritic is really meant to be, and why reviews can be full of sh*t.

Game reviews, as almost other content in the Internet, include the post you are reading, are opinions. It’s opinion, just like you and me, but the only thing that makes critics stand out is professionalism.

But that’s not something I’ve seen in many reviews which are listed on Metacritic.

You can either love, or hate a game. You can talk about it, openly, it’s your rights! But if you want to help your readers decide if they should  buy or play the game, based on your judgement, you have to be fair. Your opinions have to be as objective as possible. Of course, there is no such thing as “true objective” in reviews, but yours should have a reasonable amount in them.

Unfortunately, in this area of internet, clicks and views are everything. More views mean more ads impressions, ads clicks, and that mean more money.

The best known trick for clicks, is of course, controversial opinion.

Metacritic has a fairly easy review policy. The only measurable criteria is you have to have at least 30 reviews in your website, and you have to review fairly regularly. All other criteria about ethical or professionalism are indeed subjective. And that are being heavily abused.

Less known websites have been using that tactic to draw attention to their website. By giving a highly anticipated game an unreasonable low score, they create the controversy. People will urge to visit their websites to comment on the absurd review, or even sharing the reviews so their friends can attack them.

Who is benefiting? Do you have to guess?

Let’s talk about the infamous Washington Post’s Uncharted 4: A thief end review. Of 113 reviews averaging 93/100, they gave them 2/5 (equivalent to 40/100).

Or the slightly less infamous, USGamer’s Horizon: Zero Dawn review: 5/10 for a game which is otherwise rated 89/100.

Can you imagine it?

And Washington Post is not the only one. GameCritics, another less known site, has jumped in a gave the game a 50/100.

You can be harsh – that’s what famous magazine like Edge is known for – but you also need to be fair. You can criticize a game as much as you like, as long as the criticism is objective – why don’t you like it, and what it can have done better. When you bash a game because it’s not your taste, you become biased. The said review from WP was even disagreed by their staff

I’ve never disagreed more with a piece of content on our website as I have with this. haha  

The worst thing is this kind of shaggy tactic is not per review. Some sites are known to use it systematically, hoping to attract more clicks to the website:

GameCritics is just slightly better:

You see the pattern here? Well, you can expect those websites will, more often than not, give the lowest scores to a highly anticipated game, so their reviews become more visible and attract more clicks. People would go their and bash their review, like they themselves did with the game. In the end, who’s getting the benefits here?

Metacritic has changed the way we look at reviews. Before Metacritic, it’s more difficult to get a fairly balance, objective views of the game. But the good deed of Metacritic is being abused and if they don’t do anything to fight that, they will soon obsolete themselves.

Debugging Performance SQL Server Uncategorized

Useful T-SQL snippets for development and troubleshooting

This post is more of a note-to-self. These are the useful T-SQL statements which can be incredibly useful in development and troubleshooting

Turn on the IO statistics for statements run after that until set to OFF explicitly. We then switch to Messages tab to see how many IO operations were done on each table.

Find out about the statements were executed: which statements, its texts, how many reads (logical), how many time was spent on CPU and how many time was spent total

Learning Life Random thoughts ranting Tips Uncategorized

Choose your battles

This is the third part of the series: How to survive and thrive – a series for new developers to become better at their jobs. You can read the first two parts here and here.

In military, there is a term of “uphill battle”. That when you have to fight your way up a hill, when you enemy controls the top. It’s a very difficult fight and your chance of success is low. Any experienced military leader knows uphill battles are something you should avoid until there are no other options.

That also applies with any jobs. Including programming.

The truth is, you shouldn’t fight the battles you can’t win.

Catalog Commerce Episerver Performance Tips Uncategorized

Mass update catalog entries

This is something you don’t do daily, but you will probably need one day, so it might come in handy.

Recently we got a question on how to update the code of all entries in the catalog. This is interesting, because even thought you don’t update the codes that often (if at all, as the code is the identity to identify the entries with external system, such as ERPs or PIMs), it raises a question on how to do mass update on catalog entries.

    • Update the code directly via database query. It is supposedly the fastest to do such thing. If you have been following my posts closely, you must be familiar with my note regarding how Episerver does not disclose the database schema. I list it here because it’s an option, but not the good one. It easily goes wrong (and cause catastrophes), you have to deal with versions and cache, and those can be hairy to get right. Direct data manipulation should be only used as the last resort when no other option is available.
Commerce Episerver Order Performance SQL Server Uncategorized

The art of paging

No this is not really “art” – I’m just trying to have a more clickbait title. It’s more about understanding what you have at your disposal and use them for your benefits – in this case – how new SQL statement can drastically improve your performance.

In this blogpost we will look into paging feature of SQL Server. in Commerce we usually work with large set of data – millions of rows are fairly common, and it’s natural to load data by page. There is no point loading thousands, or even millions of rows in one go. First it’s not practical to display all of them. Second you’ll likely end up with an timeout exception and/or an out of memory exception. Even if you are lucky enough to get through, it’s still able to take your SQL Server instance to a knee, and transferring that much data over network will be another bottleneck for your system. So my friends, the best practice for loading data is to do it by batches, and to not load everything at once.