Journal tags: base

8

Codestin Search App

Databasing

A few years back, Craig wrote a great piece called Fast Software, the Best Software:

Speed in software is probably the most valuable, least valued asset. To me, speedy software is the difference between an application smoothly integrating into your life, and one called upon with great reluctance.

Nelson Elhage said much the same thing in his reflections on software performance:

I’ve really come to appreciate that performance isn’t just some property of a tool independent from its functionality or its feature set. Performance — in particular, being notably fast — is a feature in and of its own right, which fundamentally alters how a tool is used and perceived.

Or, as Robin put it:

I don’t think a website can be good until it’s fast.

Those sentiments underpin The Session. Speed is as much a priority as usability, accessibility, privacy, and security.

I’m fortunate in that the site doesn’t have an underlying business model at odds with these priorities. I’m under no pressure to add third-party code that would track users and slow down the website.

When it comes to making fast websites, most of the obstacles are put in place by front-end development, mostly JavaScript. I’ve been pretty ruthless in my pursuit of speed on The Session, removing as much JavaScript as possible. On the bigger pages, the bottleneck now is DOM size rather than parsing and excuting JavaScript. As bottlenecks go, it’s not the worst.

But even with all my core web vitals looking good, I still have an issue that can’t be solved with front-end optimisations. Time to first byte (or TTFB if you’d rather use an initialism that takes just as long to say as the words it’s replacing).

When it comes to reducing the time to first byte, there are plenty of factors that are out of my control. But in the case of The Session, something I do have control over is the server set-up, specifically the database.

Now I could probably solve a lot of my speed issues by throwing money at the problem. If I got a bigger better server with more RAM and CPUs, I’m pretty sure it would improve the time to first byte. But my wallet wouldn’t thank me.

(It’s still worth acknowledging that this is a perfectly valid approach when it comes to back-end optimisation that isn’t available on the front end; you can’t buy all your users new devices.)

So I’ve been spending some time really getting to grips with the MySQL database that underpins The Session. It was already normalised and indexed to the hilt. But perhaps there were server settings that could be tweaked.

This is where I have to give a shout-out to Releem, a service that is exactly what I needed. It monitors your database and then over time suggests configuration tweaks, explaining each one along the way. It’s a seriously good service that feels as empowering as it is useful.

I wish I could afford to use Releem on an ongoing basis, but luckily there’s a free trial period that I could avail of.

Thanks to Releem, I was also able to see which specific queries were taking the longest. There was one in particular that had always bothered me…

If you’re a member of The Session, then you can see any activity related to something you submitted in the past. Say, for example, that you added a tune or an event to the site a while back. If someone else comments on that, or bookmarks it, then that shows up in your “notifications” feed.

That’s all well and good but under the hood it was relying on a fairly convuluted database query to a very large table (a table that’s effectively a log of all user actions). I tried all sorts of query optimisations but there always seemed to be some combination of circumstances where the request would take ages.

For a while I even removed the notifications functionality from the site, hoping it wouldn’t be missed. But a couple of people wrote to ask where it had gone so I figured I ought to reinstate it.

After exhausting all the technical improvements, I took a step back and thought about the purpose of this particular feature. That’s when I realised that I had been thinking about the database query too literally.

The results are ordered in reverse chronological order, which makes sense. They’re also chunked into groups of ten, which also makes sense. But I had allowed for the possibility that you could navigate through your notifications back to the very start of your time on the site.

But that’s not really how we think of notifications in other settings. What would happen if I were to limit your notifications only to activity in, say, the last month?

Boom! Instant performance improvement by orders of magnitude.

I guess there’s a lesson there about switching off the over-analytical side of my brain and focusing on actual user needs.

Anyway, thanks to the time I’ve spent honing the database settings and optimising the longest queries, I’ve reduced the latency by quite a bit. I’m hoping that will result in an improvement to the time to first byte.

Time—and monitoring tools—will tell.

Style legend

There’s a new proposal for giving developers more control over styling form controls. I like it.

It’s clearly based on the fantastic work being done by the Open UI group on the select element. The proposal suggests that authors can opt-in to the new styling possibilities by declaring:

appearance: base;

So basically the developer is saying “I know what I’m doing—I’m taking the controls.” But browsers can continue to ship their default form styles. No existing content will break.

The idea is that once the developer has opted in, they can then style a number of pseudo-elements.

This proposal would apply to pretty much all the form controls you can think of: all the input types, along with select, progress, meter, buttons and more.

But there’s one element more that I wish were on the list:

legend

I know, technically it’s not a form control but legend and fieldset are only ever used within forms.

The legend element is notoriously annoying to style. So a lot of people just don’t bother using it, which is a real shame. It’s like we’re punishing people for doing the right thing.

Wouldn’t it be great if you, as a developer, had the option of saying “I know what I’m doing—I’m taking the controls”:

legend {
  appearance: base;
}

Imagine if that nuked the browser’s weird default styles, effectively turning the element into a span or div as far as styling is concerned. Then you could style it however you wanted. But crucially, if browsers shipped this, no existing content would break.

The shitty styling situation for legend (and its parent fieldset) is one of those long-standing annoyances that seems to have fallen down the back of the sofa of browser vendors. No one’s going to spend time working on it when there are more important newer features to ship. That’s why I’d love to see it sneak in to this new proposal for styling form controls.

I was in Amsterdam last week. Just like last year I was there to help out Vasilis’s students with a form-based assignment:

They’re given a PDF inheritance-tax form and told to convert it for the web.

Yes, all the excitement of taxes combined with the thrilling world of web forms.

(Side note: this time they were told to style it using the design system from the Dutch railway because the tax office was getting worried that they were making phishing sites.)

I saw a lot of the same challenges again. I saw how students wished they could specify a past date or a future date in a date picker without using JavaScript. And I saw them lamenting the time they spent styling legends that worked across all browsers.

Right now, Mason Freed has an open issue on the new proposal with his suggestion to add some more elements to consider. Both legend and fieldset are included. That gets a thumbs-up from me.

Mismatch

This seems to be the attitude of many of my fellow nerds—designers and developers—when presented with tools based on large language models that produce dubious outputs based on the unethical harvesting of other people’s work and requiring staggering amounts of energy to run:

This is the future! I need to start using these tools now, even if they’re flawed, because otherwise I’ll be left behind. They’ll only get better. It’s inevitable.

Whereas this seems to be the attitude of those same designers and developers when faced with stable browser features that can be safely used today without frameworks or libraries:

I’m sceptical.

Browser support

There was a discussion at Clearleft recently about browser support. Rich has more details but the gist of it is that, even though we were confident that we had a good approach to browser support, we hadn’t written it down anywhere. Time to fix that.

This is something I had been thinking about recently anyway—see my post about Baseline and progressive enhancement—so it didn’t take too long to put together a document explaining our approach.

You can find it at browsersupport.clearleft.com

We’re not just making it public. We’re releasing it under a Creative Commons attribution license. You can copy this browser-support policy verbatim, you can tweak it, you can change it, you can do what you like. As long you include a credit to Clearleft, you’re all set.

I think this browser-support policy makes a lot of sense. It certainly beats trying to browser support to specific browsers or version numbers:

We don’t base our browser support on specific browser names and numbers. Instead, our support policy is based on the capabilities of those browsers.

The more organisations adopt this approach, the better it is for everyone. Hence the liberal licensing.

So next time your boss or your client is asking what your official browser-support policy is, feel free to use browsersupport.clearleft.com

Baseline progressive enhancement

Support for view transitions for regular websites (as opposed to single-page apps) will ship in Chrome 126. As someone who’s a big fan—to put it mildly—I am very happy about this!

Hopefully Firefox and Safari won’t be too far behind. But it’s still worth adding view transitions to your website even if not every browser supports them. They’re the perfect example of a progressive enhancement.

The browsers that don’t yet support view transitions won’t be harmed in any way if you give them the CSS for view transitions. They’ll just ignore it. For users of those browsers, nothing changes.

Then when those browsers do ship support for view transitions, your website automatically gets an upgrade for those users. Code you’ve already written starts working from one day to the next.

Don’t wait, is what I’m saying.

I really like the Baseline initiative as a way to track browser support. It’s great to see it in use on MDN and Can I Use. It’s very handy having a glanceable indication of which browser features are newly available and which are widely available.

But…

Not all browser features work the same way. For features that work as progressive enhancements you don’t need to wait for them to be widely available.

Service workers. Preference queries. View transitions.

If a browser doesn’t support one of those features, that’s fine. Your website won’t break in that browser.

Now that’s not true of all browser features, particularly some JavaScript APIs. If a feature is critical for your site to function then you definitely want to wait until it’s widely supported.

Baseline won’t tell you the difference between those two different kinds of features.

I don’t want Baseline to get too complicated. Like I said, I really like how it’s nice and glanceable right now. But it would be nice if there way some indication that a newly-available feature is a progressive enhancement.

For now it’s up to us to make that distinction. So don’t fall into the trap of thinking that just because a feature isn’t listed as widely-available you can’t use it yet.

Really you want to ask two questions:

  1. How widely available is this feature?
  2. Can this feature be used as a progressive enhancement?

If Baseline tells you that the answer to the first question is “newly-available”, move on to the second question. If the answer to that is “no, it can’t be used as a progressive enhancement”, don’t ship that feature in production just yet.

But if the answer to that second question is “hell yeah, it’s a progressive enhancement!” then go for it, regardless of the answer to the first question.

Y’know, there’s a real irony in a common misunderstanding around progressive enhancement: some people seem to think it’s about not being able to use advanced browser features. In reality it’s the opposite. Progressive enhancement allows you to use advanced browser features even before they’re widely supported.

Server Timing

Harry wrote a really good article all about the performance measurement Time To First Byte. Time To First Byte: What It Is and Why It Matters:

While a good TTFB doesn’t necessarily mean you will have a fast website, a bad TTFB almost certainly guarantees a slow one.

Time To First Byte has been the chink in my armour over at thesession.org, especially on the home page. Every time I ran Lighthouse, or some other performance testing tool, I’d get a high score …with some points deducted for taking too long to get that first byte from the server.

Harry’s proposed solution is to set up some Server Timing headers:

With a little bit of extra work spent implementing the Server Timing API, we can begin to measure and surface intricate timings to the front-end, allowing web developers to identify and debug potential bottlenecks previously obscured from view.

I rememberd that Drew wrote an excellent article on Smashing Magazine last year called Measuring Performance With Server Timing:

The job of Server Timing is not to help you actually time activity on your server. You’ll need to do the timing yourself using whatever toolset your backend platform makes available to you. Rather, the purpose of Server Timing is to specify how those measurements can be communicated to the browser.

He even provides some PHP code, which I was able to take wholesale and drop into the codebase for thesession.org. Then I was able to put start/stop points in my code for measuring how long some operations were taking. Then I could output the results of these measurements into Server Timing headers that I could inspect in the “Network” tab of a browser’s dev tools (Chrome is particularly good for displaying Server Timing, so I used that while I was conducting this experiment).

I started with overall database requests. Sure enough, that was where most of the time in time-to-first-byte was being spent.

Then I got more granular. I put start/stop points around specific database calls. By doing this, I was able to zero in on which operations were particularly costly. Once I had done that, I had to figure out how to make the database calls go faster.

Spoiler: I did it by adding an extra index on one particular table. It’s almost always indexes, in my experience, that make the biggest difference to database performance.

I don’t know why it took me so long to get around to messing with Server Timing headers. It has paid off in spades. I wish I had done it sooner.

And now thesession.org is positively zipping along!

Baseline

Jake gave a great talk at Responsive Day Out 3 all about nuanced progressive enhancement, with a look at service workers in particular (a technology designed with progressive enhancement at its heart).

To illustrate the performance gains, Jake used his SVGOMG site as an example—a really terrific resource for optimising SVGs.

SVGOMG requires JavaScript for its core functionality (optimising an SVG file). That was a deliberate choice. Jake could’ve made the barrier-to-entry as low as any browser that supports input type="file" but he decided that for this audience (developers) it was a safe assumption that JavaScript would be available.

Jake talked about this in an interview with Paul about the site:

I’m a strong believer in progressive enhancement, but also that each phase of the enhancement needs a user.

I agree completely with this approach. It makes sense to have a valid reason for adding any enhancement. But there’s something about this particular example that wasn’t sitting right with me. It took me a while to figure it out, but I now realise what it is.

Jake is talking about making it work on the server as an enhancement. But that’s not an enhancement, it’s a fallback.

Thinking in terms of fallbacks is more of a “graceful degradation” approach (i.e. for every “full” feature, thinking of a corresponding fallback). That’s not how I like to think of progressive enhancement. I like to think in terms of a baseline. And that baseline, in my mind, does not require a user to justify its existence. That’s because the baseline isn’t there to cover the use cases we can think of, it’s there to cover the use cases we can’t predict.

That might seem like a minor difference in wording to the graceful degradation approach but I think it’s actually a fundamentally different way of approaching the situation.

When I was on the progressive enhancement panel at Edge Conf, Lyza asked how low the baseline should be. I said “as low as possible.” Some of my fellow panelists took issue with this saying it varies from project to project, and that’s completely true, but I think I should’ve clarified that when I talk about a baseline, I’m not talking about browsers. I don’t think about a baseline in terms of “IE4 and above, Android 2.1 and above, etc.”—I think about a baseline in terms of “the minimum required technology to allow a user to accomplish the core task” (that qualification about core tasks is important—the baseline does not need to cover tasks that are nice-to-have; those can safely require more sophisticated technology).

That “minimum required technology” often turns out to be a combination of a web server, HTTP, and some HTML.

So to take SVGOMG as an example, I would begin with the baseline of “allowing a user to optimise an SVG file”. The minimum required technology is a web server running a programme that does the optimisation, and an HTML document that contains a form element with input type="file". Once that’s in place, then I can start applying Jake’s very sensible approach of thinking about enhancements in terms of specific user benefits. In this case, it’s pretty clear that 99.99% of the users would benefit from not having that round-trip to the server and have the SVG optimisation happen in the browser using JavaScript.

There’s an enhancement provided for the use case that I can imagine. But—and this is the subtle but important distinction—there’s a baseline for all the use cases that I can’t think of. I need to recognise that I won’t be able to predict all the possible use cases, and that’s okay—as long there’s a solid baseline in place, I’ve got an insurance policy for unforeseen circumstances. It’s still not perfect, but it lowers the risk somewhat by reducing the number of assumptions being built in at that baseline level.

Going back to Jake’s chat with Paul, he says:

I thought about making the site work without JS by doing the SVG work on the server, but this would be slow and a maintenance burden.

The maintenance burden is a very valid point. This is something that Stuart talked about a while back:

It is in theory possible to write a web app which does processing on the server and is entirely robust against its client-side scripting being broken or missing, and which does processing on the client so that it works when the server’s unavailable or uncontactable or expensive or slow. But let’s be honest here. That’s not an app. That’s two apps.

Leaving aside the promise of isomorphic/universal/whatever JavaScript, this issue of developer convenience is big issue. When I use the term “developer convenience” to label this problem, I am not belittling it in any way—developer convenience is incredibly important (hence the appeal of so many tools and frameworks that make life easier for developers). I still believe that developer convenience should be lower on the list of priorities than having a rock-solid baseline, but I can totally understand if someone doesn’t share that opinion. It’s a personal decision and if the pain involved in making a more universal baseline is greater than the perceived—and, let’s face it, somewhat abstract—benefit, I can totally understand that.

Anyway, that’s my little brain dump about progressive enhancement and baseline experiences. Something about treating the baseline experience as an enhancement was itching at my brain and now that I’ve managed to scratch it, I can see what was troubling me: thinking about the baseline experience in the same way as thinking about enhancements doesn’t work for me.

Personally, I’m going to strive to keep the baseline as low as possible. I’m also going to strive to apply Jake’s maxim about every enhancement requiring a user.

Helvetican crossing

One of the services we offer at Clearleft is on-site training… a bit of this, a bit of that. It’s something that I really enjoy. Not only do I get to spend a day talking incessantly about the technologies that tickle my fancy, I also get to travel and meet web developers who are digging away at the coalface behind their company firewalls.

Thus far, our little roadshow has travelled within the UK to companies in London, York, and elsewhere. This week, we’re spreading our wings a little further. On Friday, I’ll be doing some DOM Scripting training in Basel, Switzerland located right on the nexus of France, Germany and the Confoederatio Helvetica.

It won’t be my first time to Basel. I’ve been there on a few occasions, mostly for the unique annual spectacle of the Morgensterich carnival. I used to live fairly close by, over the border in Freiburg, Germany.

I arrived in Freiburg many years ago with my bouzouki in hand and started busking on the streets. I ended up staying for about five or six years. Along the way I met Jessica, worked in a bakery and played bass in a surf-rock band. Then that whole web thing came along and set me on my present course.

I haven’t been back to Freiburg since moving to England six years ago. Seeing as I’m going to be in Basel anyway, I think I’ll take a trip up to the old town this weekend. I’ll revisit my old haunts and revisit the beer and wurst while I’m at it.

I hope my German hasn’t become too rusty in the intervening time. I guess I’ll find out if I’m able to comprehend the Schweizerdeutsch spoken in Basel.

Expect my Flickr photostream to fill up with pictures of Freiburg’s quaint alleyways and its wonderful cathedral. Tchüß… bis später.