<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Антон Темербеков</title>
    <description>The latest articles on DEV Community by Антон Темербеков (@temer).</description>
    <link>https://dev.to/temer</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4066436%2F5bec8e1d-c49b-4aba-b030-953c5a23b229.jpg</url>
      <title>DEV Community: Антон Темербеков</title>
      <link>https://dev.to/temer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/temer"/>
    <language>en</language>
    <item>
      <title>We analysed 24 million ratings of human faces. Four things surprised us</title>
      <dc:creator>Антон Темербеков</dc:creator>
      <pubDate>Thu, 13 Aug 2026 07:43:31 +0000</pubDate>
      <link>https://dev.to/temer/we-analysed-24-million-ratings-of-human-faces-four-things-surprised-us-5baf</link>
      <guid>https://dev.to/temer/we-analysed-24-million-ratings-of-human-faces-four-things-surprised-us-5baf</guid>
      <description>&lt;p&gt;We run an app where people upload a photo and get rated from 1 to 10 by strangers around the world. It has been running since 2014. In that time the database has collected &lt;strong&gt;24,097,993 submitted ratings&lt;/strong&gt; from 109,821 people across 232 countries — plus 8.4 million skips, where someone looked at a photo and moved on without scoring it.&lt;/p&gt;

&lt;p&gt;This is not a scientific sample, and I'll get to the limitations in a moment. But data like this is hard to come by: academic work on attractiveness perception typically runs on hundreds of participants and dozens of photographs. Here we have twelve years of continuous observation of how people judge other people's faces. I went into our own PostgreSQL and found four things I did not expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the limitations
&lt;/h2&gt;

&lt;p&gt;This is data from one app, not from humanity. The people here actively chose to be rated — a very particular sample. Country comes from the city in the user's profile, not from geolocation. Gender is self-declared. We don't know who is actually in the photo.&lt;/p&gt;

&lt;p&gt;So everything below is about &lt;strong&gt;the behaviour of the raters&lt;/strong&gt;, not about who is better looking. The question "which country has the most attractive people" is meaningless in this data, and I'm not asking it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 1: nobody gives a nine
&lt;/h2&gt;

&lt;p&gt;The first thing that jumps out of the distribution is the hole at nine. A ten is given &lt;strong&gt;3.4× more often&lt;/strong&gt; than a nine: 14.6% versus 4.3%. Between "eight" and "ten" people barely stop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdq8m7k3nqzq51btfoare.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdq8m7k3nqzq51btfoare.png" alt="Distribution of 24 million ratings across the 1-10 scale, with a spike at 5 and a hole at 9" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The single most common answer is five, at 24.45%. That's the slider's default position, and a quarter of raters simply never move it. Harsh scores are rare: ratings 1 through 4 together account for 12.4%.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Ratings&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;476,591&lt;/td&gt;
&lt;td&gt;1.98%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;602,882&lt;/td&gt;
&lt;td&gt;2.50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;898,204&lt;/td&gt;
&lt;td&gt;3.73%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1,009,530&lt;/td&gt;
&lt;td&gt;4.19%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5,892,680&lt;/td&gt;
&lt;td&gt;24.45%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3,548,185&lt;/td&gt;
&lt;td&gt;14.72%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;4,379,993&lt;/td&gt;
&lt;td&gt;18.18%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2,719,997&lt;/td&gt;
&lt;td&gt;11.29%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;1,042,271&lt;/td&gt;
&lt;td&gt;4.33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;3,527,681&lt;/td&gt;
&lt;td&gt;14.64%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A ten doesn't seem to work as a point on the scale — it works as a separate gesture. It means "wow", not "nine plus one". A nine demands that you weigh something; a ten doesn't. Anyone who has collected NPS scores or five-star reviews knows this shape: people cluster at the ends and on round numbers instead of spreading across the range.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: men punish men
&lt;/h2&gt;

&lt;p&gt;This is the sharpest gap in the entire dataset. Women rate men and women almost identically — 6.45 and 6.32. Men rate women 6.54, and other men &lt;strong&gt;5.40&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fikzeqggsqfote3tesp1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fikzeqggsqfote3tesp1c.png" alt="Average rating by rater gender and target gender: men rating men stands out at 5.40" width="799" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a gap of &lt;strong&gt;1.14 points&lt;/strong&gt; between how a man rates a woman and how the same man rates another man. The equivalent gap for women is 0.13 points — essentially zero.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pair&lt;/th&gt;
&lt;th&gt;Ratings&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Man → man&lt;/td&gt;
&lt;td&gt;780,766&lt;/td&gt;
&lt;td&gt;5.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Woman → woman&lt;/td&gt;
&lt;td&gt;1,410,741&lt;/td&gt;
&lt;td&gt;6.32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Woman → man&lt;/td&gt;
&lt;td&gt;2,617,973&lt;/td&gt;
&lt;td&gt;6.45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Man → woman&lt;/td&gt;
&lt;td&gt;19,288,521&lt;/td&gt;
&lt;td&gt;6.54&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The effect holds across all twelve years and isn't explained by sample size. I can't tell from the data what drives it: competition, disinterest, or simply that a man looking at a man is answering a different question — not "is he good looking" but "is he better than me". But the size of the gap is hard to write off as noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: a 2.4-point spread between countries
&lt;/h2&gt;

&lt;p&gt;The same photo will get a noticeably different score depending on who is looking at it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk8shhmygzru0zehr204.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnk8shhmygzru0zehr204.png" alt="Deviation from the global mean by country: Norway highest, Ukraine lowest" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a methodological detail worth dwelling on. My first pass put East Timor, Anguilla and Senegal at the top of the generosity ranking — and that turned out to be a pure artefact. All 5,942 of East Timor's ratings came from &lt;strong&gt;a single user&lt;/strong&gt;; Anguilla and Senegal had three raters each. Once I required at least 100 distinct raters per country, the picture became meaningful:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Country&lt;/th&gt;
&lt;th&gt;Raters&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Norway&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;7.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Czechia&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;7.21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mexico&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;td&gt;6.96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canada&lt;/td&gt;
&lt;td&gt;726&lt;/td&gt;
&lt;td&gt;6.89&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netherlands&lt;/td&gt;
&lt;td&gt;213&lt;/td&gt;
&lt;td&gt;6.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Belgium&lt;/td&gt;
&lt;td&gt;145&lt;/td&gt;
&lt;td&gt;5.88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Romania&lt;/td&gt;
&lt;td&gt;121&lt;/td&gt;
&lt;td&gt;5.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Türkiye&lt;/td&gt;
&lt;td&gt;224&lt;/td&gt;
&lt;td&gt;5.84&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hungary&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;5.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ukraine&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;5.48&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And a separate detail that breaks intuition: &lt;strong&gt;people are harsher on their own&lt;/strong&gt;. When rater and rated are from the same country the average is 6.34; when they're from different countries it's 6.48. The difference is small but stable across four million ratings, and it points the opposite way from what you'd guess. Shared nationality works against you here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 4: the first ten ratings of the day are the kindest
&lt;/h2&gt;

&lt;p&gt;I ordered each person's ratings within a day: first of the day, second, tenth, hundredth. People start generous and harden fairly quickly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz0j27il8m5bnxnyw9ebx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz0j27il8m5bnxnyw9ebx.png" alt="Average rating falls from 6.98 in the first ten of the day to 6.27 by the fiftieth" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first ten ratings of a day average 6.98. By the fiftieth-to-hundredth the average has fallen to 6.27 — a drop of 0.71. After that the curve turns back up: people who reach three hundred ratings in a day score higher again, but that's a different, much smaller audience that's into the process itself.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Position in day&lt;/th&gt;
&lt;th&gt;Ratings&lt;/th&gt;
&lt;th&gt;Average&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1–10&lt;/td&gt;
&lt;td&gt;283,457&lt;/td&gt;
&lt;td&gt;6.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11–25&lt;/td&gt;
&lt;td&gt;178,691&lt;/td&gt;
&lt;td&gt;6.66&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26–50&lt;/td&gt;
&lt;td&gt;130,570&lt;/td&gt;
&lt;td&gt;6.31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;51–100&lt;/td&gt;
&lt;td&gt;144,877&lt;/td&gt;
&lt;td&gt;6.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101–250&lt;/td&gt;
&lt;td&gt;188,050&lt;/td&gt;
&lt;td&gt;6.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;250+&lt;/td&gt;
&lt;td&gt;265,438&lt;/td&gt;
&lt;td&gt;6.51&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There's a practical lesson here for anyone who collects ratings of anything — CVs, contest entries, products: &lt;strong&gt;presentation order affects the result more than you'd think&lt;/strong&gt;. The difference between reaching a reviewer fifth and fiftieth is roughly seven tenths of a point out of ten. If you don't randomise order, you aren't measuring quality — you're measuring position in the queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to take from this
&lt;/h2&gt;

&lt;p&gt;None of these numbers say anything about how anyone actually looks. All four findings are about the rater: their fatigue, their gender, their culture, their relationship with the scale. The person looking at your photo brings far more to it than you'd assume from the number that comes back.&lt;/p&gt;

&lt;p&gt;Age plays a part too: the harshest raters are 18–24 (6.14), rising to 6.64 among 35–44 year olds. The effect is real but weaker than the others, so I left it out of its own section.&lt;/p&gt;

&lt;p&gt;All aggregates were computed directly in PostgreSQL on production; no personal data was used or published. The app is called Rate Me. But the most useful thing to take away from these 24 million ratings is a healthy scepticism toward any single number somebody has assigned to you or your work.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>postgres</category>
      <category>analytics</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How we distribute an iOS app outside the App Store: a practical AltStore PAL walkthrough</title>
      <dc:creator>Антон Темербеков</dc:creator>
      <pubDate>Thu, 06 Aug 2026 19:52:07 +0000</pubDate>
      <link>https://dev.to/temer/how-we-distribute-an-ios-app-outside-the-app-store-a-practical-altstore-pal-walkthrough-33li</link>
      <guid>https://dev.to/temer/how-we-distribute-an-ios-app-outside-the-app-store-a-practical-altstore-pal-walkthrough-33li</guid>
      <description>&lt;p&gt;App Store review rejected our app under Guideline 1.2 — the core mechanic (users rate each other's photos) is banned as a category, and no metadata change fixes that. So we became one of the first apps distributed exclusively through an alternative marketplace under the EU's DMA. Documentation for this path is thin and sometimes contradictory, so here is a step-by-step of what actually had to be done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Alternative Terms Addendum
&lt;/h2&gt;

&lt;p&gt;You sign an addendum to the developer agreement in App Store Connect. You don't need to be an EU resident. Distribution is free up to 1M first annual installs (companies under €10M revenue get the Core Technology Fee exemption).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Registering with the marketplace
&lt;/h2&gt;

&lt;p&gt;AltStore has a REST API to register your developer ID — important: it's the UUID from your ASC profile, &lt;strong&gt;not&lt;/strong&gt; the Team ID (registering with the Team ID silently fails — we stepped on that). The token goes into ASC: Users and Access → Integrations → Marketplaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Notarization instead of review
&lt;/h2&gt;

&lt;p&gt;You build and upload with the usual xcodebuild + upload. Then, instead of "Submit for Review", you send it for notarization: an automated security/functionality check, without content guidelines. Ours passed on the first try in ~30 hours. A mechanic banned on the App Store passes here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Hosting the ADP yourself
&lt;/h2&gt;

&lt;p&gt;After notarization you download the Alternative Distribution Package: &lt;code&gt;manifest.json&lt;/code&gt;, a &lt;code&gt;signature&lt;/code&gt; file (no extension!), and several &lt;code&gt;.ipa&lt;/code&gt; variants. You host it as-is; hierarchy and hashes must not change. Two gotchas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the extensionless &lt;code&gt;signature&lt;/code&gt; file — our SPA fallback on ASP.NET served index.html instead; fixed with ServeUnknownFileTypes on the static handler;&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;.ipa&lt;/code&gt; must be served as &lt;code&gt;application/octet-stream&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5. Source JSON and federation
&lt;/h2&gt;

&lt;p&gt;Next to it you put a &lt;code&gt;source.json&lt;/code&gt;: marketplaceID (= the app's Apple ID), the manifest downloadURL, size, icon, screenshots, versions. Users add the source via an &lt;code&gt;altstore://source?url=…&lt;/code&gt; link. Enable federation (a &lt;code&gt;fediUsername&lt;/code&gt; field) and the app becomes searchable right inside the marketplace, no manual source add.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;p&gt;Each new version is the same loop: build → notarize → new ADP on the server → new entry in &lt;code&gt;versions[]&lt;/code&gt; of source.json. AltStore picks up auto-updates itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits and fallbacks
&lt;/h2&gt;

&lt;p&gt;Marketplaces work in the EU, Japan and Brazil, iOS 17.4+. For the rest of the world we run a PWA (standalone manifest + a minimal service worker — Safari installs it to the home screen) and a sideload IPA via AltStore Classic with our own source. The biggest non-technical problem is conversion: you have to explain to users what a marketplace even is, so we funnel all traffic to a single install page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;Cost beyond the developer account: zero. Actual time spent: about a week, most of it on the undocumented details above. If the App Store is closed to your app (or you just don't want to hand over 15–30%), this path works today.&lt;/p&gt;

&lt;p&gt;The app from this case study is Rate Me (rateme.lv/ios) — happy to answer questions in the comments.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>apple</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
