How will I have to update "views_count" each time(!) a user loads my page? It will be costly. And I don't need such accuracy when I update "views_count" after a user loads a page.

Then is there any way to buffer "views_count" to somewhere so that I'll be able to update a field in database in one fell swoop, say, by +5 once in N minutes?

How is it usually implemented?


I would suggest updating the counter on each view. As @amon suggested - that hard part is determining WHEN to update the counter.

An old adage - no premature optimization before its time. Meaning- don't write complicated code for a problem you don't have yet.

You & others asked whether this is a performance issue - and I'll counter by asking -- Why would it be? Do you have evidence that makes you worry?

You can and should Model this quickly using napkin math - how many people do you realistically expect on your site per day - break that down to per hour or per minute. Do you expect 1 million? or 1,000? or 100?

Gather your existing web log stats to help model this (if available). And if this is an internal website for a company -- the total employee count is the largest you need to worry about.

Break the yearly down to an hourly stat (and there may be 5 days in a week if you expect access only on Business days). Use the fraction New vs Repeat users - multiply by the hourly page view stat to determine how often the counter is updating. Play with the number -- start with 70/30 (Repeat/New). Guess if you can't find good stats from your product manager. What if it is 1/99 or 99/1? Is that a concerning result?

I have found that the numbers tend to be much smaller than initially imagined - and you'll see that a computer can easily handle it.

Just write the code in a way that you can insert/refactor should you have a problem. There are lots of patterns out there.

For example: https://docs.microsoft.com/en-us/azure/architecture/patterns/

| improve this answer | |
  • 1
    Ah yes, I too was a serial pre-optimiser, and it got me into plenty of trouble! The best compromise I would say (only if the napkin math doesn't confound it entirely) is to provide a level of abstraction such that (in this case) you simply tell some other service to increase the count, but what that service does is entirely independent of the article displaying itself. Simply make it simple for the time being, and if need be you can later swap out for a more featureful one. – Daniel Park Sep 7 '17 at 3:38
  • Yes and... usually the performance problem is no where near where you imagined it would be. – ripvlan Sep 8 '17 at 14:49

You want a view counter for each page, so yes, you will have to increment a counter upon each view. This is unlikely to be a performance problem for the vast majority of web sites.

The difficult part isn't maintaining that view counter efficiently, but deciding what counts as a view, and why you need this counter in the first place. E.g. you might want to exclude page loads from bots. You might want to count multiple page loads from the same user as a single view, e.g. if they reload the page. You might want to ignore views if the user immediately navigates away. You might actually be looking for an off-the-shelf analytics solution.

So depending on how you define a “view” you will have to store different kinds of data, possibly a complete event log. That will likely involve a database, though the specific technology choices will be influenced by your existing architecture.

After you have a working solution and find that it can't cope with the torrent of views (probably once you pass 50 views per second regularly), you can think about optimizing the solution. If you won't join the view counts with other data, a simple key–value store that is separate from your main DB may be a good fit, and can be scaled in the future. Though that would be overkill as your initial solution.

| improve this answer | |
  • This is unlikely to be a performance problem for the vast majority of web sites. -- why not? – Dari Sep 6 '17 at 15:10
  • suppose, I'm able to distinguish between a unique and non unique user. but why would I update "view_count" in a db each time a unique user comes? why not to buffer several unique view and after that update a db and clear a buffer ? – Dari Sep 6 '17 at 15:12
  • 1
    @Dari This is unlikely to be a perf problem because OP's site is probably part of the long tail of websites that aren't exactly Facebook-scale. For comparison, this Software Engineering site gets up to 120K views per day which is less than 2 views per second on average – a very manageable load for literally any web stack. – amon Sep 6 '17 at 15:37
  • 1
    Caching may become sensible if your DB is throughput limited (if your site is latency-limited, async DB updates would be a better idea). But caching introduces concurrency issues that can be tricky to work around (assuming you have multiple servers/processes/threads). You may also lose views if the server process terminates before the cache could be persisted to the DB. Since the view counter is per-page, caching only helps noticeably for popular pages (e.g. landing pages or viral posts), i.e. if you track multiple views per page per buffer window. For all other pages it's just memory overhead – amon Sep 6 '17 at 15:40
  • For comparison, this Software Engineering site gets up to 120K views per day which is less than 2 views per second on average –..... -- does this mean that I can update a db by "update view_count set ...." every second, when a new user comes, without any issue related to performance? – Kumaro Sep 7 '17 at 6:02

In highly scalable application, you will inevitably require multiple machines to process your workload, and these machines usually will be distributed over multiple data center with fair amount of latency between these data centers.

In such scenarios, a distributed counter can be implemented not by updating a number, but by appending to a distributed log graph database. The reason to use a log graph is that you don't need to hold a global lock to append to a DAG-log, and you will get an eventually consistent global count. The log graph is later pulled and aggregated by a view counter process for a group of machines (a local reducer), who then submits the subtotals to a central aggregator (a global reducer).

Note that this kind of distributed counting solution has a very large constant factor. On smaller scales, a well optimized integer increment is a lot simpler and will perform much better than a distributed counter could ever do. Most applications would never have enough traffic for this to be worthwhile.

| improve this answer | |

Apart from what others have said, I believe you can detach view counts from the page rendering and loading process by making an Ajax call to external web api in a different server. Either develop and deploy your own web api for stats or use a web site statistic provider like Google Analytics, StatCounter, etc. Then you'll be able to synchronize your DB by calling their web api for retrieving stats.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.